Question

I have a class with two overrides for == operator, to compare it to other instances of this class, and to compare to instance of string.

class SomeClass
{
    string value;
    public SomeClass (string _Value)
    {
        value = _Value;
    }

    static public bool operator == (SomeClass C1, SomeClass C2)
    {
        return C1.value == C2.value;
    }

    static public bool operator != (SomeClass C1, SomeClass C2)
    {
        return C1.value != C2.value;
    }

    static public bool operator == (SomeClass C1, string C2)
    {
        return C1.value == (string) C2;
    }

    static public bool operator != (SomeClass C1, string C2)
    {
        return C1.value != (string) C2;
    }
}

However, when I try to compare this class to null:

        Console.WriteLine(someObject == null);

I get the following error:

Error CS0121: The call is ambiguous between the following methods or properties: `SomeClass.operator ==(SomeClass, SomeClass)' and `SomeClass.operator ==(SomeClass, string)'

How should I define my == overrides so I can still null-check instances of this class?

Was it helpful?

Solution

Since you're using a null literal, the compiler doesn't know which method to call since both string and SomeClass can be null.

One technique to force the compiler to choose one of the methods is to typecast the null.

Console.WriteLine(someObject == ((SomeClass)null));

Or better yet, instead of using null explicitly, use the default keyword to get the null value (because default(T) is null when T is a reference type).

Console.WriteLine(someObject == default(SomeClass));

OTHER TIPS

Rather than defining two equality operators, you could create an implicit conversion between string and SomeClass:

class SomeClass
{
    string value;
    public SomeClass(string _Value)
    {
        value = _Value;
    }
    static public bool operator ==(SomeClass C1, SomeClass C2)
    {
        return C1.value == C2.value;
    }
    static public bool operator !=(SomeClass C1, SomeClass C2)
    {
        return C1.value != C2.value;
    }

    public static implicit operator string(SomeClass instance)
    {
        return instance.value;
    }

    public static implicit operator SomeClass(string str)
    {
        return new SomeClass(str);
    }
    //TODO override Equals and GetHashCode to use `value`
}

Now when you compare the value with null there is no ambiguity issue.

This also has the side effect of making the classes implicitly convertible to each other everywhere else, but based on the context that doesn't seem to be a bad thing.

You can pass 2nd param as "object" and check its type before deciding which equality to do.

static public bool operator == (SomeClass C1, object C2)
{
  if(C2 is SomeClass)
    return C1.value == ((SomeClass)C2).value;
  else if (C2 is string)
    return C1.value == (string) C2;
}

For those coming late to this please refer below for the more acceptable answer which is hidding in comments from @Jeppe Stig Nielsen.

The op has asked specifically about overriding operator == , however, I believe this is an important piece of information when overriding the == operator and believe the correct answer for future reference should be:-

Console.WriteLine((object)someObject == null);

Using the accepted answer and implementing both == and Equals in your object, you will continue to get same error. Best to compare to null at the lowest level object, that way you are comparing 'object' to null and all ambiguity is removed from the comparison.

Here is the reason and resolution as per implemented in MSDN: Guidelines for Overriding Equals() and Operator ==

Consider the following, refer the comments in the Equals implementation:-

class SomeClass
{
    string value;
    public SomeClass(string _Value)
    {
        value = _Value;
    }

    static public bool operator ==(SomeClass C1, SomeClass C2)
    {
        return C1.value == C2.value;
    }

    public override bool Equals(SomeClass C1)
    {
        // causes error due to unsure which operator == to use the SomeClass == or the object ==
        // Actual error: Operator '==' is ambiguous on operands of type 'SomeClass' and '<null>'
        if (C1 == null)
            return false;

        // Give same error as above
        if (C1 == default(SomeClass))
            return false;

        // Removes ambiguity and compares using base objects == to null
        if ((object)C1 == null)
            return false;

        return value == C1.value;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top