0

I'm writing a bit of code, and there is a part that gives me hassles. I'm having the following structure in my code:

foreach (Node node in nodes)
{
    try
    {
        bool n = node.previous == null;
    }
    catch (Exception e)
        {
            StreamWriter s = new StreamWriter("error.txt");
            s.WriteLine(e.Message);
            s.WriteLine("-----------");
            s.Close();
        }
}

In here Node is a custom type, the node.prev variable is also a custom type (Location). Running this gives the following error-log:

Object reference not set to an instance of an object.
-----------

I'm 100% sure that node isn't null (which should be made impossible by foreach = Not true, sorry!). Also, as you can see in the following listing, the Node.previous is set to null at declaration:

public class Node
{
    public Location previous = null;
    public Location location;
    public int distance;
    ...
    ...
}

I have no idea how I can fix these exeptions occuring, and I'm kind of at the end of having any ideas on how to solve this. Can anybody help me with this?

Note that these are all not the final code, but I sifted the parts that didn't matter!

Thanks in advance, Delpee

EDIT: Ricovox helped me to the solution with this answer, thanks a lot!

Community
  • 1
  • 1
Yuri van Geffen
  • 853
  • 1
  • 7
  • 21
  • 4
    1) Which line is throwing the exception? 2) If you don't know where the error is happening how do you know the rest of the code doesn't matter? – Rotem Dec 18 '12 at 19:05
  • Have you put a breakpoint on that line of code? What are the values? Is nodes null? – Wonko the Sane Dec 18 '12 at 19:05
  • I can't put a breakpoint, because this is for Google's AI challenge, which has a weird system making it impossible to debug the classical way. I know this is the problem because this is where the exception is caught. – Yuri van Geffen Dec 18 '12 at 19:10
  • _"I'm 100% sure that node isn't null (which should be made impossible by foreach)."_ As others have said, most likely, `node` is null. The statement that you made leads me to believe you have a misconception on what `foreach` actually does – Mark Hildreth Dec 18 '12 at 19:14
  • I'm pretty sure I know what Foreach does (and I'm still 100% sure it will not be null). This fixed it: bool n = Nullable.Equals(null,node.prev); – Yuri van Geffen Dec 18 '12 at 19:27
  • I'm glad that you resolved your issue, but your wording made is sound as if using a foreach loop prevented the resulting items from being null. That probably sent up red flags to a lot of people that node was null, since your explanation for why it is not didn't make sense. – Mark Hildreth Dec 18 '12 at 19:33
  • I'm sorry about that, reading back it does! I actually checked it for being null, was what made me so sure. I'll try to construct my phrases more careful next time! Thanks for the effort anyway! – Yuri van Geffen Dec 18 '12 at 19:38
  • Almost all cases of NullReferenceException are the same. Please see "[What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net)" for some hints. – John Saunders Dec 18 '12 at 22:53
  • I would set a breakpoint in your foreach line and see whether my nodes has members or not! you can trace what is happening using System.Diagnostics.Debug.WriteLine("current node:"+ node.Location.ToString()+...); – IT Seeker Dec 18 '12 at 19:08
  • You can write to the output window with [tracepoints](http://msdn.microsoft.com/en-us/library/232dxah7(v=vs.100).aspx) without having to update your code. – Wonko the Sane Dec 18 '12 at 19:11

6 Answers6

4

The most likely problem is that node is null!. There is nothing about the foreach statement that would prevent node from being null, because in general an IEnumerable object (e.g. a list or collection) CAN contain null as a valid item.

No error would be thrown if previous is null (unless the node.prev class/struct overrides the == operator).

As others have mentioned, put in a test like this to verify:

foreach (Node node in nodes)
{
    bool n;
    try
    {
        if (node == null) 
        {
           n = true; //do something to deal with a null node
        }
        else 
        {
          n = node.previous == null;
        }
    }
    catch (Exception e)
    {
        StreamWriter s = new StreamWriter("error.txt");
        s.WriteLine(e.Message);
        s.WriteLine("-----------");
        s.Close();
    }
}
drwatsoncode
  • 4,721
  • 1
  • 31
  • 45
  • 1
    I'm not the most unexperienced programmer, I've checked for node being null, it isn't in any case (that's why I was so sure). Fixed it thanks to ricovox: bool n = Nullable.Equals(null,node.prev); – Yuri van Geffen Dec 18 '12 at 19:24
  • Sorry for assuming you were a newbie :-) If you had mentioned the google challenge and that you had already verified that node wasn't ever null, that would have put your question in a different perspective :-) As it turns out, it seems like this was a pretty good test google used, because people don't often consider operator overrides, and they CERTAINLY don't expect those overrides to throw exceptions for common comparisons like `(x==null)`. So it's definitely understandable that this error would cause some confusion! Good luck with the rest of the challenge!! – drwatsoncode Dec 18 '12 at 19:30
4

So I'm posting another answer in response to your comment:

"I have checked for node being null, it isn't, at any point."

If that IS true, there here are some other options;

  1. Take a look at the node.previous class/struct definition. It COULD implement a CUSTOM == operator that throws an error when compared to null. As an example, think about the Nullable<T> type. It has an overloaded == operator that returns true if the HasValue property is false (obviously, since it is a struct it isn't truly null, but overloading the operator gives the desired behavior.) To fix this, you could test object.ReferenceEquals(node.previous, null) which wouldn't be overloaded. If you have access to change the node.previous definition, perhaps you can find out why the overloaded operator throws an exception when compared to null (which it obviously shouldn't)

  2. nodes could be null, in which case it is the foreach statement that is throwing the error. Test nodes == null before the foreach.

---------------Edit---------------

As Jeppe pointed out, my analogy with Nullable<T> (in option #1, above) could be misleading (in fact it did confuse the discussion, although the point itself was correct). In order to better illustrate the idea of overriding the == operator, I've posted an example below that demonstrates the Container type. This type is a struct, so it can never be null itself, but it contains a single Value object. (The point of this struct is that you can work with any Container object without worrying whether or not it is null, even though the contained Value object might be null). The main thing to note is that when a Container is compared with == to null, the result will be true if Value is null, which would NOT be true if the == operator weren't overridden (because a struct can never be null).

public struct Container {
    public object Value { get; set; }
    public bool IsNull { get { return Value == null; } }
    public static bool operator ==(Container x, object y) { return x.Equals(y); }
    public static bool operator !=(Container x, object y) { return !x.Equals(y); }
    public override bool Equals(object obj) {
        if (obj is Container)
            return Value == ((Container)obj).Value;
        return Value == obj;
    }
    public override int GetHashCode() { return Value == null ? 0 : Value.GetHashCode(); }
}

////---------Test----------
var x = new Container { Value = null };
var y = new Container { Value = "hi" };
var z = new Container { Value = null };
Print(x == null); //true 
Print(x == y);    //false
Print(x == z);    //true

And just in case you are wondering how overriding == would affect a class, I've written another example below that demonstrates a Box class. It's similar to the Container struct, except that we have to deal with the case in which the Box object is null itself. Note that in this case, there is another surprising result of overriding ==. Two reference types can be equal (==) to each other, even if they reference different objects, as long as they have equal Value properties.

public class Box {
    public static bool ItemsEqual(object x, object y) {
        object xval, yval;
        xval = x is Box ? (x as Box).Value : x;
        yval = y is Box ? (y as Box).Value : y;
        return xval == yval;
    }
    public object Value { get; set; }
    public bool IsNull { get { return Value == null; } }
    public static bool operator ==(Box x, object y) { return ItemsEqual(x, y); }
    public static bool operator !=(Box x, object y) { return !ItemsEqual(x, y); }
    public override bool Equals(object obj) { return ItemsEqual(this, obj); }
    public override int GetHashCode() { return Value == null ? 0 : Value.GetHashCode(); }
}

////---------Test----------
object n = null;
Box w = null;
Box x = new Box { Value = null };
Box y = new Box { Value = "hi" };
Box z = new Box { Value = "hi" };

Print(w == null);  //true (uses overridden '==' because w is defined as a Box)
Print(w == n);     //true
Print(x == w);     //true 
Print(x == null);  //true 
Print(x == n);     //true 

Print(w == y);    //false
Print(x == y);    //false
Print(y == z);    //true (actual ref's differ, but values are ==)
Community
  • 1
  • 1
drwatsoncode
  • 4,721
  • 1
  • 31
  • 45
  • Thanks, this fixed it: bool n = Nullable.Equals(null,node.prev); – Yuri van Geffen Dec 18 '12 at 19:20
  • Was `node.prev` actually a nullable type? You could have just gotten lucky because maybe the overloaded operator had an error, but the `Equals` override didn't. – drwatsoncode Dec 18 '12 at 19:23
  • 1
    Node.Prev is nullable, yes, but it's type (Location) had a custom '==' operator, which couldn't handle null (not my code! :P), which caused the problem. – Yuri van Geffen Dec 18 '12 at 19:30
  • I think you mean that the `Location` type is "nullable" in the sense that it can set to null, but it isn't actually a `Nullable`, right? Unless google uses alternate versions of the framework dlls, `Nullable` is a struct which cannot be inherited. So there is no way `Location` could be a true `Nullable`. – drwatsoncode Dec 18 '12 at 19:45
  • Since `Location` is NOT a `Nullable`, I would avoid using `Nullable.Equals`. Instead use `object.Equals` to compare `Node.Prev` with null. If `Node.Prev` is a class (NOT a ValueType) it would be even better to use `ReferenceEquals(Node.Prev, null)` just in case `Location.Equals(object x)` method is overridden. I haven't checked, but my assumption is that `Nullable.Equals` will call object.Equals in the event that neither argument is a `Nullable`. So your code probably WILL work fine, but a more correct answer would not use Nullable to compare objects that are not `Nullable`. – drwatsoncode Dec 18 '12 at 19:52
  • No, I don't think location is a Nullable, but as it is a custom class, I should be able to set a value of type Location to null, shouldn't I? I will try ReferenceEquals instead ;). – Yuri van Geffen Dec 18 '12 at 19:52
  • @Delpee OK, so `Location` was a **class** overloading the `==` operator in an incorrect way? Can you please show the `class` declaration for `Location` including the `==` operator? You must fix the wrong implementation of `==`. Saying `Nullable.Equals(null, node.previous)` is meaningless! It will actually call `object.Equals` because the overload defined in the `Nullable` static class does not apply. So it ends up calling the override of the virtual `object.Equals(object)` which I really hope your `Location` class has. So use `ReferenceEquals`, or use `(object)(node.previous) == (object)null`. – Jeppe Stig Nielsen Dec 18 '12 at 22:22
  • ricovox: It is possible to misunderstand your analogy with the `Nullable` struct. It is not a perfect analogy because: **(1)** the [`Nullable` struct (see for yourself)](http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx) does not actually (in the .NET Framework itself) overload the `==` operator. This "overload" is the **lifted operator** defined in the C# Language Specification, and the compiler creates the required logic (checking `HasValue` and so on). And **(2)** if you really had to compare two `Nullable`, it would be catastrophic to use `ReferenceEquals` because of boxing. – Jeppe Stig Nielsen Dec 18 '12 at 22:50
1

If nodes were null the exception would occur before the loop, and the exception wouldn't be caught.

Since the previous member is a simple field, the only possibility I see is that one of the node members of your nodes collection is null. You can do this:

foreach (Node node in nodes)
{
  if (node == null)
    throw new Exception("I told you so");
}

EDIT: OK, it turned out there was one possibility I didn't see, and that was a broken overload of the == operator. To make sure you call the usual overload, say:

foreach (Node node in nodes)
{
  bool n = (object)(node.previous) == (object)null;
}

(actually it will suffice to cast just one side of the == operator to object), or equivalently use ReferenceEquals:

foreach (Node node in nodes)
{
  bool n = object.ReferenceEquals(node.previous, null);
}

But you must fix the wrong implementation of the == overload.

If you had posted the stack trace of the exception in your original question, it would have been clear to most users here on SO that the exception came from a call to your == overload. So next time, inspect your stack trace.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • You are right, I didn't notice that the try/catch block wasn't surrounding the `foreach` loop. Edited out of my answer. – e_ne Dec 18 '12 at 19:16
0

There's nothing that ensures that node is not null, since Node is not a value type. Mind giving more details?

e_ne
  • 8,340
  • 32
  • 43
0

set a breakpoint at your line that starts with bool and verify that node is not null and that nodes is not null. My guess is that either nodes is null, or else it contains a null value if it's not a type-safe list.

Paul
  • 35,689
  • 11
  • 93
  • 122
  • That is not possible, as I don't have any debugging options (sorry for mentioning). This is for the AI challenge (Google), which uses a weird system which makes debugging impossible! I have checked for node being null, it isn't, at any point. Node.prevs could be null, but that shouldn't be a problem when comparing it with null, would it? – Yuri van Geffen Dec 18 '12 at 19:08
0

I'm 100% sure that node isn't null

But I'm 100% sure that an element in nodes is null! try this:

foreach (Node node in nodes)
{
    try
    {
        if(null == node) throw new Exception("This is not expected!");
        bool n = node.previous == null;
    }
    catch (Exception e)
        {
            if(File.Exists("error.txt")) File.Delete("error.txt");
            using(StreamWriter s = new StreamWriter("error.txt")){
            s.WriteLine(e.Message);
            s.WriteLine("-----------");
            s.Close();}
        }
}
Yasser Zamani
  • 2,380
  • 21
  • 18
  • Following code doesn't create an error message: bool n = node == null; if (n) { StreamWriter s = new StreamWriter("error.txt"); s.WriteLine("n == null"); s.Close(); } – Yuri van Geffen Dec 18 '12 at 19:14
  • @user1764970, so maybe the message is in file from before; truncate the error log file for each run please...I edited the answer to do this. – Yasser Zamani Dec 18 '12 at 19:16
  • 1
    I checked it for being null, it isn't ever (I've been programming for some time, believe me, it will not be null). It's fixed, turned out that Location had a custom '==' operator, which aparently didn't handle null very good, fixed it using the following: bool n = Nullable.Equals(null,node.prev); – Yuri van Geffen Dec 18 '12 at 19:26