MSDNの==オペレーターのドキュメントによると、
定義済みの値タイプの場合、等価演算子(==)は、そのオペランドの値が等しい場合は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); } }
==、同じ型の2つのオペランドの間で許可されない型がいくつかあることを理解することは有用かもしれません。これはstruct、をオーバーロードしないタイプ(「事前定義された」タイプを除く)に当てはまりますoperator ==。簡単な例として、この試してください:var map = typeof(string).GetInterfaceMap(typeof(ICloneable)); Console.WriteLine(map == map); /* compile-time error */
var kvp1 = new KeyValuePair<int, int>(); var kvp2 = kvp1;、は構造体であり、C#の事前定義された型ではないkvp1 == kvp2ためKeyValuePair<,>、チェックできませんoperator ==。しかし、var li = new List<int>(); var e1 = li.GetEnumerator(); var e2 = e1;あなたができない例が示されていますe1 == e2(ここでは、オーバーロードしないネストされた構造体List<>.Enumerator("List`1+Enumerator[T]"ランタイムによって呼び出されます)があります==)。
boolvoid