views:

905

answers:

9

When I overload the == operator for objects I typically write something like this:

 public static bool operator ==(MyObject uq1, MyObject uq2) {
  if (((object)uq1 == null) || ((object)uq2 == null)) return false;
  return uq1.Field1 == uq2.Field1 && uq1.Field2 == uq2.Field2;
 }

If you don't down-cast to object the function recurses into itself but I have to wonder if there isn't a better way?

A: 

ReferenceEquals(object obj1, object obj2)

Juanma
This doesn't seem to actually address the issue at all - ReferenceEquals will not tell you if one is null and the other is not, for example.
Philip Rieck
Why are people voting this up, from my example it is clear that ReferenceEquals is not what I'm looking for
George Mauer
+6  A: 

This article seems to be exactly what you are looking for.

neouser99
Downcast to object is the best way then? sigh
George Mauer
A: 
if ((object)uq1 == null) 
    return ((object)uq2 == null)
else if ((object)uq2 == null)
    return false;
else
    //return normal comparison

This compares them as equal when both are null.

Timothy Carter
This does the same thing that my example does just in more convoluted terms
George Mauer
A: 

Follow the DB treatment:

null == <anything> is always false
Purfideas
This does not address the concern, x == y if one is null will recurse the function as I have said
George Mauer
+2  A: 

@neouser99: That's the right solution, however the part that is missed is that when overriding the equality operator (the operator ==) you should also override the Equals function and simply make the operator call the function. Not all .NET languages support operator overloading, hence the reason for overriding the Equals function.

Scott Dorman
Really? That is interesting, I've been doing it the other way around
George Mauer
If you do it this way, make sure the == operator checks for null. null == null always.
Joe Hildebrand
+1  A: 

As Microsoft says,

A common error in overloads of operator == is to use (a == b), (a == null), or (b == null) to check for reference equality. This instead results in a call to the overloaded operator ==, causing an infinite loop. Use ReferenceEquals or cast the type to Object, to avoid the loop.

So use ReferenceEquals(a, null) || ReferenceEquals(b, null) is one possibility, but casting to object is just as good (is actually equivalent, I believe).

So yes, it seems there should be a better way, but the method you use is the one recommended.

However, as has been pointed out, you really SHOULD override Equals as well when overriding ==. With LINQ providers being written in different languages and doing expression resolution at runtime, who knows when you'll be bit by not doing it even if you own all the code yourself.

Philip Rieck
Yes, it's a common problem but the solution is to override the Equals function and make the operator overload call Equals. ReferenceEquals solves a different problem and provides a completely different type of equality.
Scott Dorman
I think you misunderstood the ReferenceEquals calls above. I'm simply testing for equality with NULL, with the understanding of doing an actual equality check in addition. NOT calling referenceequals to test equality of the arguments.
Philip Rieck
+2  A: 

This is a duplicate of the post found here.

Abe Heidebrecht
A: 

But why don't you create an object member function? It can certainly not be called on a Null reference, so you're sure the first argument is not Null.

Indeed, you lose the symmetricity of a binary operator, but still...

(note on Purfideas' answer: Null might equal Null if needed as a sentinel value of an array)

Also think of the semantics of your == function: sometimes you really want to be able to choose whether you test for

  • Identity (points to same object)
  • Value Equality
  • Equivalence ( e.g. 1.000001 is equivalent to .9999999 )
xtofl
I'm sorry this really doesn't answer the question. The question is if there is a better way to test for equality other than downcasting
George Mauer
A: 

Just use Resharper to create you Equals & GetHashCode methods. It creates the most comprehensive code for this purpose.

Update I didn't post it on purpose - I prefer people to use Resharper's function instead of copy-pasting, because the code changes from class to class. As for developing C# without Resharper - I don't understand how you live, man.

Anyway, here is the code for a simple class (Generated by Resharper 3.0, the older version - I have 4.0 at work, I don't currently remember if it creates identical code)

public class Foo : IEquatable<Foo>
{
    public static bool operator !=(Foo foo1, Foo foo2)
    {
        return !Equals(foo1, foo2);
    }

    public static bool operator ==(Foo foo1, Foo foo2)
    {
        return Equals(foo1, foo2);
    }

    public bool Equals(Foo foo)
    {
        if (foo == null) return false;
        return y == foo.y && x == foo.x;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(this, obj)) return true;
        return Equals(obj as Foo);
    }

    public override int GetHashCode()
    {
        return y + 29*x;
    }

    private int y;
    private int x;
}
ripper234
And you wouldn't by any chance want to post it for those of us who don't have $400 to drop?
George Mauer