views:

220

answers:

4

Hello.

I overloaded the == operator on my class as follows:

public static bool operator ==(Table pt1, Table pt2) {
    return Compare(pt1, pt2) == 0 && pt1.TableName == pt2.TableName;
}

Compare will work just as the strcmp does in c++, returning an integer. Problem is that if I do an if (MY_CLASS == null), it will call my == operator, and thus my Compare function. What is the alternatiev? to put an check on pt1 and pt2 to see if they are null? Or just in pt2?

+2  A: 

Just add this line to your operator:

if ((object)pt1 == null || (object)pt2 == null) return false;

The (object) cast is there to prevent recursion (from calling object.== instead of MY_CLASS.==.

Although I'm not sure of the conditions that should arise when comparing null to null.

MiffTheFox
Will this work? I would think the cast here wouldn't make any difference since override methods are virtual.
Tal Pressman
You don't *override* ==, you *overload* it.
Jon Skeet
+3  A: 

You will need the null checks to get the correct behaviour. The clearest way to add this check in my opinion is to call object.ReferenceEquals(x, null), since it is a straight non-polymorphic method call and presumably fairly efficient.

jerryjvl
+9  A: 

You should checkout Microsoft's guidelines for implementing the '==' operator and also for overriding 'Equals()'.

Adapting their example you'd want something like:

public static bool operator ==(Table a, Table b)
{
    // If both are null, or both are same instance, return true.
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    // If one is null, but not both, return false.
    if (((object)a == null) || ((object)b == null))
    {
        return false;
    }

    // Return true if the fields match:
    return Compare(a, b) == 0 && a.TableName == b.TableName;
}
Luke Quinane
I'd either use object.ReferenceEquals in both places or use the cast in both places, if you see what I mean.
Jon Skeet
+1  A: 

I asked a similar question here. Have a look at it.

    public bool Equals(ClauseBE other)
    {
        if (this._id == other._id)
        {
            return true;
        }
        return false;
    }

    public override bool Equals(Object obj)
    {
        if (obj == null)
        {
            return base.Equals(obj);
        }

        if (!(obj is ClauseBE))
        {
            throw new InvalidCastException("The 'obj' argument is not a ClauseBE object.");
        }

        return Equals(obj as ClauseBE);
    }

    public override int GetHashCode()
    {
        return this._id.GetHashCode();
    }


    public static bool operator ==(ClauseBE a, ClauseBE b)
    {
        if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
        {
            return true;
        }

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
        {
            return false;
        }

        return a.Equals(b);
    }

    public static bool operator !=(ClauseBE a, ClauseBE b)
    {
        return !(a == b);
    }
Matthew Vines