How to test for null in operator == overload?

  • Thread starter Thread starter Steve Sargent
  • Start date Start date
S

Steve Sargent

Hi:

I'm trying to debug the following code, and it keeps looping on the if
statement:

public static bool operator ==
(OnlineMemberNode first, OnlineMemberNode second)
{
if(first == null)
{
return false;
}

...
}

I've set my breakpoint to the if condition, and it keeps looping
there, eventually causing a stack overflow. I don't understand. In
my testing, the first is an object of type AdminMode (inherits from
OnlineMemberNode).

Is there another way to test for an undefined value. Originally,
because the second parameter is undefined, when I call the member
variables to do the testing, I get a null pointer exception.

I think the problem is that each time I test the first parameter for
null, I'm recursively calling itself to perform the same test.
However, I don't really know a way around this.

How do I get around this endless loop?

Thanks for any help in advance.

Steve
 
What happens if you do

if(first != null)
{
if(second != null)
{
//if same
return true;
}
}
return false;
 
Sounds normal to me. Did you try:

if ((object)first == null)

This one should not go into an infinite recursion.

Bruno.
 
You'll run into the same infinite recursion problem if you also overload !=
(and you should do it).

You have to cast first/second to object to force it to use the default == or
!= rather than the overloaded one.

Bruno.
 
ironically, my test for != has a similar test for null

public static bool operator !=
(someObjectType first, someObjectType second)

{
....
}

in here, I can use either (first == null) test, or the
(first != null) test. Either one will cause a loop back through
one of the static methods. basically, this will still cause an
infinite loop.
 
Didn't try that. Thank you. This is good to know.

Ironically, by luck
(my best technique :-) ), testing with the "is" keyword worked for me.

if I run (first is someObject) test, it works. At least in my app.
I'll need to test this out with other scenarios to see if this
is a full answer, or just a partial answer for my specific
information.
 
Yes, the "is" test will work but it does something slightly different, it
tests whether "first" is an instance of your class or not, rather than
whether "first" is null or not.

Bruno.
 
That's what I would believe too, by the signature. However, testing
this against both a object of same type initialized to null, and a
literal value of null, produced the desired results. (tried to test
against an uninitialized object, but compiler wouldn't allow it). So,
for whatever reasons, (at least in the 1.1 framework), this worked.

However, it's nice to know this isn't the only way of doing it. It
sure would have been nice if this issue would have been covered in the
MSDN example.
(ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/csref/html/vcwlkoperatoroverloadingtutorial.htm)
Their version assumes both values not null. No test for null is done
is even considered. Of course, this seems to be the motto for most of
their examples; only partially complete.

Steve
 
In this particular case (when I've overloaded the == and != operators), I
tend to use ReferenceEquals(first, null) to check for nulls. I believe that
this shows the correct intention the best. I'm not sure what the best way
is performance-wise, but that's not a big issue most of the time.

My initial solution to this problem (when I first encountered it) was to use
(object)first == null, which also works fine. Since this is an upcast I
think there will be no performance hit---I would assume that it would be
similar in performance to ReferenceEquals. However, I decided against it
for the sake of readability. Still, the intent is (for the most part) clear
in either case.

Casting with "as" will also work, but there's a slight performance hit
that's not needed. You already know that the value is of your type (or
null), so you don't need to check that again.

(Off topic a bit) Ugh.. I hate incomplete examples like that. It's like the
early examples everyone wrote for strongly-typed collections using
CollectionBase where most of the time they didn't bother to provide an
OnValidate implementation. Doing so turns a type-safe collection into a
potentially unsafe one, as anyone can just case your collection to IList and
add whatever objects they want.

The MSDN example in question here is technically correct, though, since they
are overloading operators on a struct. ValueTypes (and therefore structs)
cannot be null, so there's no need to check for null. I find myself
overloading operators on structs far more often than on classes, due to the
value semantics of structs, but whenever the need for a *class* with
overloaded operators comes up I always have to think twice about my operator
implementations. I've made the same mistake as you a few times. There are
simply a lot more issues to worry about in classes when dealing with
operators. I tend to follow System.String's example though, and only do so
with immutable, sealed classes, so they act just like valuetypes. You don't
have to deal with reference semantics and problems with derived classes
breaking usage.

--Matthew W. Jackson
 
Matthew W. Jackson said:
In this particular case (when I've overloaded the == and != operators), I
tend to use ReferenceEquals(first, null) to check for nulls. I believe that
this shows the correct intention the best. I'm not sure what the best way
is performance-wise, but that's not a big issue most of the time.

My initial solution to this problem (when I first encountered it) was to use
(object)first == null, which also works fine. Since this is an upcast I
think there will be no performance hit---I would assume that it would be
similar in performance to ReferenceEquals.

There's no performance hit, because the cast doesn't really exist - it
just tells the compiler which version of the == method to use. (And
indeed, it basically tells it to use a single IL instruction to compare
references in this case).

(Off topic a bit) Ugh.. I hate incomplete examples like that. It's like the
early examples everyone wrote for strongly-typed collections using
CollectionBase where most of the time they didn't bother to provide an
OnValidate implementation. Doing so turns a type-safe collection into a
potentially unsafe one, as anyone can just case your collection to IList and
add whatever objects they want.

I thoroughly recommend writing to MSDN (using the link at the bottom of
each page) when you come across a problem in the documentation, whether
it's a coding mistake or whatever. I've found they've been very good at
changing the documentation (although it takes a while before you see
the difference, of course). Only through lots of people taking the
attitude of "when something's wrong, I'll let them know" will the
standard of documentation increase significantly.
 
Back
Top