对于具有==运算符的几个覆盖的类,空检查是不明确的

时间:2013-08-05 17:43:43

标签: c# operator-overloading equality null-check

我有一个带有两个覆盖==运算符的类,将它与该类的其他实例进行比较,并与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;
    }
}

但是,当我尝试将此类与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 个答案:

答案 0 :(得分:7)

由于您使用的是null文字,因此编译器不知道要调用哪个方法,因为stringSomeClass都可以为空。

强制编译器选择其中一种方法的一种技术是对null进行类型转换。

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

或者更好的是,不是显式使用null,而是使用default关键字来获取空值(因为当T是引用类型时,default(T)为空)。

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

答案 1 :(得分:5)

您可以在stringSomeClass之间创建隐式转换,而不是定义两个相等运算符:

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进行比较时,没有歧义问题。

这也有副作用,使类在其他地方可以隐式地相互转换,但是基于看起来不是坏事的上下文。

答案 2 :(得分:1)

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

op已经具体询问了覆盖operator ==,但是,我相信这是覆盖==运算符时的一个重要信息,并且相信未来引用的正确答案应该是: -

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

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

以下是MSDN中实施的原因和解决方案:Guidelines for Overriding Equals() and 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;
    }
}

答案 3 :(得分:0)

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

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