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

Max*_*kov 9 c# equality operator-overloading 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将此类与null进行比较时:

        Console.WriteLine(someObject == null);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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

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

voi*_*hos 8

由于您使用的是null文字,编译器不知道,因为既要调用哪个方法string,并SomeClass可以为空.

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

Console.WriteLine(someObject == ((SomeClass)null));
Run Code Online (Sandbox Code Playgroud)

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

Console.WriteLine(someObject == default(SomeClass));
Run Code Online (Sandbox Code Playgroud)

  • @golergka现在,根据您在问题中展示的实际实现,您的“==”重载都可能会因“NullReferenceException”而爆炸。也许您想要 C# 内置重载“operator ==(object, object)”(实际上不是 IL 中的方法)?我想你做到了。所以这就是 `someObject == (object)null` 或 `(object)someObject == null` 或 `(object)someObject == (object)null` (这三个都转到内置的 `==`,而不是您的任何操作员)。 (2认同)

Ser*_*rvy 6

您可以在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`
}
Run Code Online (Sandbox Code Playgroud)

现在,当您将值与null进行比较时,就不会出现歧义问题。

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