views:

100

answers:

3

Hey guys,

So I have a class which overrides Equals(object obj) and GetHashCode() along with implementing IEquatable. To make working with this type a little more natural when checking for equality I thought, heck, I'd overload the equality operator and inequality operator, no worries...

Uh oh, worries... consider the following - where both myType instances are NOT null:

if (myType != container.myType) //NullReferenceException
{
    //never get here
}
//never get here either

Now, container is just another class to hold an instance of myType among other things which is used for caching items.

Here's the actual (relevant) code from myType:

public class MyType : IEquatable<MyType>
{
    public static bool operator ==(MyType myTypeA, MyType myTypeB)
    {
        return myTypeA.Equals(myTypeB);
    }

    public static bool operator !=(MyType myTypeA, MyType myTypeB)
    {
        return !(myTypeA == myTypeB);
    }

    public override bool Equals(object obj)
    {
        if (obj != null && obj is MyType)
        {
            return Equals((MyType)obj);
        }
        return false;
    }

    public bool Equals(MyType other)
    {
        if (other != null)
        {
            return other.ToString() == ToString();
        }
        return false;
    }
}

Any experience on this front?

Thanks.

+2  A: 

Tricky one... the problem is that you use the equality operator inside the Equal override as follows:

public bool Equals(MyType other)
{
    if (other != null)

It goes to your overloaded != operator, which in turn goes to your == operator, which trying to do null.Equals...

Amittai Shapira
Sorry, browsing with Chrome threw me off-shot: Advertisements allowed me to miss further posts! Spot on though. Thanks.
Mr. Disappointment
+3  A: 

Couple of pointers -

  1. If you've overridden == and != on classes, make sure to use ReferenceEquals to check for null inside the overload implementations rather than ==, as that will call your overloaded operator and either go into a loop or try to call Equals on a null this reference, which is probably what is happening here.
  2. Don't override == and != on classes. Those operators are meant for value equality, and classes aren't really designed to have value equality. Either remove the operator overloads, or make MyType a struct.
thecoop
Thanks, this, and a little more patience in stepping through code with not missing a call, has allowed me to realise that Equals was in fact being called with null as the comparison which led to a call to the equality operator with null, which led to another call to Equals with null, which led to another equality operator call with two nulls, and BANG. Could have been worse, could have had a dreaded loop.
Mr. Disappointment
+1  A: 

As the others have stated you need to be carefull checking for nulls as it will call your equality function again, normally resulting in a StackOverflowException.

When I use the IEquatable interface on classes I normally use the following code:

public override bool Equals(object obj)
{
    // If obj isn't MyType then 'as' will pass in null
    return this.Equals(obj as MyType);
}

public bool Equals(MyType other)
{
    if (object.ReferenceEquals(other, null))
    {
        return false;
    }

    // Actual comparison code here
    return other.ToString() == this.ToString();
}
Sam