12

我有一个类,有两个覆盖 == 运算符,将其与此类的其他实例进行比较,并与字符串的实例进行比较。

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)'

我应该如何定义我的 == 覆盖,以便我仍然可以对此类的实例进行空检查?

4

4 回答 4

12

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));
于 2013-08-05T17:48:37.197 回答
8

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`
}

现在,当您将该值与 null 进行比较时,没有歧义问题。

这也具有使类在其他任何地方隐式相互转换的副作用,但基于上下文,这似乎不是一件坏事。

于 2013-08-05T17:52:19.910 回答
1

您可以将第二个参数作为“对象”传递并在决定要执行哪个相等之前检查其类型。

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;
}
于 2013-08-05T17:54:05.980 回答
1

对于那些迟到的人,请参阅下面的更可接受的答案,该答案隐藏在@Jeppe Stig Nielsen 的评论中。

该操作已专门询问覆盖运算符 == ,但是,我相信这是覆盖 == 运算符时的重要信息,并相信未来参考的正确答案应该是:-

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

使用接受的答案并在您的对象中实现 == 和 Equals,您将继续收到相同的错误。最好在最低级别的对象上与 null 进行比较,这样您就可以将“object”与 null 进行比较,并且从比较中删除所有歧义。

以下是 MSDN 中实施的原因和解决方案:Overriding Equals() 和 Operator == 指南

考虑以下内容,请参阅 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;
    }
}
于 2015-12-19T05:32:52.250 回答