20

==Equals()with exampleはどう違いますか?==演算子を比較するために使用され、文字列の内容を比較するためにメソッドが使用されることを知っていEquals()ます。だから私は試しました

// first example
string s1 = "a";
string s2 = "a";
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2,
                             // then result will be false

// second example
string s1 ="a";
string s2 ="a";
Console.Write(s1 == s2);     // returns true

これはどうしてですか?どちらも異なるオブジェクト参照です。これらを参考に考えてみましょう。しかし、私はこのように使用しようとしました

string s1 = new string("ab");
string s2 = new string("ab");

文字列を文字に変換できないというコンパイル時エラーが発生しています

4

3 に答える 3

26

いくつかのことが起こっています。まず、この例では:

string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);

あなたはそれを主張します:

どちらも異なるオブジェクト参照です。

string interningのため、これは当てはまりません。s1s2は同じオブジェクトへの参照です。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)
于 2012-03-02T07:20:46.827 に答える
7

Equalsのドキュメントからの引用:

Equals の既定の実装では、参照型の参照の等価性と、値型のビットごとの等価性がサポートされています。参照の等価性とは、比較されるオブジェクト参照が同じオブジェクトを参照することを意味します。ビットごとの等価性は、比較されるオブジェクトが同じバイナリ表現を持つことを意味します。

そして== 演算子:

定義済みの値の型の場合、等価演算子 (==) は、オペランドの値が等しい場合は true を返し、そうでない場合は false を返します。文字列以外の参照型の場合、2 つのオペランドが同じオブジェクトを参照している場合、== は true を返します。文字列型の場合、== は文字列の値を比較します。

質問に戻ります。なぜ returns1 == s2が true なのですか? 文字列は .NET の特殊な動物です。それらは不変の参照型を表します。彼らは .NET に収容されています。これは、同じ値を持つ 2 つの文字列定数がある場合、実行時に同じオブジェクト インスタンスを参照することを意味します。

ドキュメントからの引用:

共通言語ランタイムは、インターン プールと呼ばれるテーブルを維持することで、文字列ストレージを節約します。このテーブルには、プログラムでプログラムによって宣言または作成された一意の各リテラル文字列への単一の参照が含まれています。したがって、特定の値を持つリテラル文字列のインスタンスは、システム内に 1 回だけ存在します。

于 2012-03-02T07:19:05.640 に答える
2

あなたはJava風だと思っています。Java では==演算子をカスタマイズできないため、参照型の場合は常に参照の等価性を意味し、プリミティブ型の場合は値の等価性を意味します。一方、Equals参照型の値の等価性をチェックするためのものです。

ただし、C# では状況が異なります。との両方Equals==カスタム実装を含めることができます。違いは、それEqualsが仮想 (インスタンス) メソッドであるのに対し、operator==は静的メソッドであることです。それ以外は、まったく同じように動作できます。

デフォルトでは、両方Equals==リファレンスタイプの参照等式を確認し、値タイプの値平等を確認します。ただし、string両方とも価値の平等を確認するためにカスタマイズされています。

于 2012-03-02T07:25:34.063 に答える