C# では演算子 == をジェネリック型に適用できないのでしょうか? 質問する

C# では演算子 == をジェネリック型に適用できないのでしょうか? 質問する

==オペレーターの文書によると、マイクロソフト

定義済みの値型の場合、等価演算子 (==) は、そのオペランドの値が等しい場合は true を返し、そうでない場合は false を返します。文字列以外の参照型の場合、== は、2 つのオペランドが同じオブジェクトを参照する場合に true を返します。文字列型の場合、== は文字列の値を比較します。ユーザー定義の値型は、== 演算子をオーバーロードできます (演算子を参照)。ユーザー定義の参照型も同様にオーバーロードできますが、デフォルトでは == は定義済みの参照型とユーザー定義の参照型の両方に対して上記のように動作します。

では、なぜこのコード スニペットはコンパイルに失敗するのでしょうか?

bool Compare<T>(T x, T y) { return x == y; }

演算子 '==' は、型 'T' および 'T' のオペランドには適用できませんというエラーが表示されます。私の理解では、==演算子はすべての型に対して事前定義されているのに、なぜでしょうか?

編集:皆さん、ありがとうございます。最初は、この記述が参照型のみに関するものであることに気づきませんでした。また、すべての値型に対してビットごとの比較が提供されていると思っていましたが、今ではそれが正しくないことがわかっています。

しかし、参照型を使用している場合、演算子は==定義済みの参照比較を使用するのでしょうか、それとも型で定義されている場合は演算子のオーバーロードされたバージョンを使用するのでしょうか?

編集 2:試行錯誤の結果、==制限のないジェネリック型を使用する場合、演算子は定義済みの参照比較を使用することがわかりました。実際には、コンパイラは制限された型の引数に対して見つけられる最良の方法を使用しますが、それ以上は検索しません。たとえば、以下のコードは、 が呼び出されたtrue場合でも常に を出力します。Test.test<B>(new B(), new B())

class A { public static bool operator==(A x, A y) { return true; } }
class B : A { public static bool operator==(B x, B y) { return false; } }
class Test { void test<T>(T a, T b) where T : A { Console.WriteLine(a == b); } }

ベストアンサー1

他の人が言っているように、これは T が参照型に制約されている場合にのみ機能します。制約がない場合、null と比較することはできますが、null のみであり、その比較は null 非許容値型では常に false になります。

Equals を呼び出す代わりに、IComparer<T>- を使用する方が適切です。さらに情報がない場合は、EqualityComparer<T>.Defaultが適切な選択です。

public bool Compare<T>(T x, T y)
{
    return EqualityComparer<T>.Default.Equals(x, y);
}

何よりも、これによりボクシング/キャスティングが回避されます。

おすすめ記事