我有一个类,它有两个==运算符的重写,用于将其与该类的其他实例进行比较,并与字符串的实例进行比较。
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;
}
}
然而,当我尝试将这个类与null进行比较时:
Console.WriteLine(someObject == null);
我得到以下错误:
Error CS0121: The call is ambiguous between the following methods or properties: `SomeClass.operator ==(SomeClass, SomeClass)' and `SomeClass.operator ==(SomeClass, string)'
我应该如何定义我的==覆盖,这样我仍然可以空检查这个类的实例?
由于使用的是null
文字,编译器不知道该调用哪个方法,因为string
和SomeClass
都可以为null。
强制编译器选择其中一种方法的一种技术是对null进行类型转换。
Console.WriteLine(someObject == ((SomeClass)null));
或者更好的是,不要显式使用null
,而是使用default
关键字来获取null值(因为当T是引用类型时,default(T)
是null)。
Console.WriteLine(someObject == default(SomeClass));
您可以在string
和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`
}
现在,当您将值与null进行比较时,不存在歧义问题。
这也有副作用,使类在其他任何地方都可以隐式地相互转换,但基于上下文,这似乎并不是一件坏事。
您可以将第二个参数作为"对象"传递,并在决定执行哪个等式之前检查其类型。
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;
}
对于那些迟到的人,请参阅下面的@Jeppe Stig Nielsen的评论中隐藏的更可接受的答案。
操作人员特别询问了覆盖运算符==的问题,然而,我认为这是覆盖==运算符时的一条重要信息,并认为未来参考的正确答案应该是:-
Console.WriteLine((object)someObject == null);
使用接受的答案并在对象中实现==和Equals,您将继续得到相同的错误。最好在最低级别的对象中与null进行比较,这样您就可以将"object"与null进行对比,并从对比中消除所有歧义。
以下是MSDN中实现的原因和解决方案:重写等于()和运算符==的指南
考虑以下内容,请参阅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;
}
}