いくつかのことが起こっています。まず、この例では:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
あなたはそれを主張します:
どちらも異なるオブジェクト参照です。
string interningのため、これは当てはまりません。s1
とs2
は同じオブジェクトへの参照です。C# 仕様は次のことを保証します - C# 4 仕様のセクション 2.4.4.5 から:
文字列等値演算子 (§7.10.7) に従って等しい文字列リテラルが 2 つ以上同じプログラムにある場合、これらの文字列リテラルは同じ文字列インスタンスを参照します。
object.ReferenceEquals(s1, s2)
したがって、この特定のケースでは、 を印刷した場合でも、または との真の参照同一性比較を使用した場合でも、「真」になります==
。
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
ただし、これらが別のオブジェクトへの参照であったとしても、==
はに対してオーバーロードされstring
ます。オーバーロードはコンパイル時の決定です。使用する実装は、オペランドのコンパイル時の型によって異なります。たとえば、次のようになります。
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a == b); // Uses string's implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
object.Equals(object)
それを仮想メソッドと比較してください。たまたま、String
このメソッドもオーバーロードしますが、重要なことに、それをオーバーライドします。したがって、コードを次のように変更すると:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
...その後、コンパイルされたコードの両方のメソッド呼び出しは単純に toobject.Equals(object)
になりますが、ポリモーフィズムのために両方とも True を出力します: の実装String
が使用されます。
オーバーロードされたメソッドの呼び出しは次のようになります。
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)