Zero checking is ambiguous for a class with several overrides for the == operator

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

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 with 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 do I define overrides == == =========================================== =================================================== ===================================================

+8
equality c # operator-overloading null-check
source share
4 answers

Since you are using a null literal, the compiler does not know which method to call, since both string and SomeClass may be empty.

One way to get the compiler to select one of the methods is to enter a null value.

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

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

 Console.WriteLine(someObject == default(SomeClass)); 
+6
source share

Instead of defining two equality operators, you can 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 that you are comparing a value with a null value, there is no ambiguity problem.

It also has a side effect of the fact that classes are implicitly converted to each other everywhere, but based on a context that doesn't seem bad.

+4
source share

For those who are late for this, see below a more acceptable answer, which is forbidden in the comments by @Jeppe Stig Nielsen.

Op specifically asked about the redefinition of the == operator, however, I believe that this is an important part of the information when redefining the == operator, and believe that 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 receive the same error. It is best to compare with zero on the lowest level object, so you compare the "object" with zero, and any ambiguity is removed from the comparison.

The following is the reason and resolution on MSDN: Recommendations for Overriding Equals () and Operators ==

Consider the following: comments in the implementation of Equals: -

 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; } } 
+1
source share

You can pass the second parameter as an “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; } 
-one
source share

All Articles