12

== 演算子の 2 つのオーバーライドを持つクラスがあり、このクラスの他のインスタンスと比較し、文字列のインスタンスと比較します。

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 チェックできるように、== オーバーライドをどのように定義すればよいですか?

4

4 に答える 4

12

リテラルを使用しているためnull、コンパイラはどちらのメソッドを呼び出すかわかりませstringSomeClass

コンパイラにメソッドの 1 つを強制的に選択させる 1 つの手法は、null を型キャストすることです。

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

nullまたは、明示的に使用する代わりに、defaultキーワードを使用して null 値を取得します ( default(T)T が参照型の場合は null であるため)。

Console.WriteLine(someObject == default(SomeClass));
于 2013-08-05T17:48:37.197 に答える
8

string2 つの等価演算子を定義する代わりに、との間の暗黙的な変換を作成できます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

これに遅れている人は、@Jeppe Stig Nielsen からのコメントに隠れている、より受け入れられる回答について以下を参照してください。

op は特に operator == のオーバーライドについて尋ねましたが、これは == 演算子をオーバーライドする際の重要な情報であり、将来の参照のための正しい答えは次のとおりであると考えています:-

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

受け入れられた回答を使用し、オブジェクトに == と Equals の両方を実装すると、引き続き同じエラーが発生します。最下位レベルのオブジェクトで null と比較するのが最善です。そのようにして、「オブジェクト」を null と比較し、すべてのあいまいさが比較から削除されます。

MSDN で実装されている理由と解決策は次のとおりです。Equals() および演算子をオーバーライドするためのガイドライン ==

次の点を考慮してください。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 に答える
1

2番目のパラメーターを「オブジェクト」として渡し、そのタイプを確認してから、どちらを行うかを決定できます。

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 に答える