2012-03-19 2 views
8
 string s1 = "t"; 
     string s2 = 't'.ToString();   

     Console.WriteLine(s1.Equals(s2)); // returning true 
     Console.WriteLine(object.Equals(s1, s2)); // returning true 

ここでは同じ結果が返されます。今私がStringBuilderを使用しているとき、同じ値を返さない。根底にある理由は何ですか?なぜobject.Equalsとinstanceobject.Equalsが同じでないか

 StringBuilder s1 = new StringBuilder(); 
     StringBuilder s2 = new StringBuilder(); 

     Console.WriteLine(s1.Equals(s2)); // returning true 
     Console.WriteLine(object.Equals(s1, s2)); // returning false 

EDIT1:私の上記の質問は以下の答え。しかし、この議論の中で、StringBuilderに実装されたEqualsメソッドはオーバーライドされていません。したがって、StringBuilder.Equalsを呼び出すと、実際にObject.Equalsに移動します。したがって、誰かがStringBuilder.EqualsとS1.Equals(S2)を呼び出した場合、結果は異なります。

+1

良いキャッチ!要するに、 'StringBuilder'は' Equals(object) 'をオーバーライドするのを忘れてしまったようです。 'Equals(StringBuilder)'が 'Equals(object)'とは異なる振る舞いを持つことは直感的ではないようです。 – leppie

答えて

7

String.Equals()は、Equal()のオーバーライドをstringで定義した場合、実際には同じ文字列がEqual()になるようにオーバーライドされています。

string literals(あなたの例ではそうではありません)を比較している場合、同じ文字列リテラルがinterned ...ということに注意する価値があります。つまり、同じ文字列が同じアドレスに存在するので、 .Equals()またはs1.ReferenceEquals(s2))、および値で指定します。

StringBuilderは、object.Equals(object obj)の代わりにs1.Equals(s2)がそのオーバーロードを呼び出すように、StringBuilderをパラメータとするEquals()へのオーバーロードを提供します。

http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.equals.aspx

StringBuilder.Equals()このインスタンスとSBが等しい文字列、容量、 MAXCAPACITY値を持っている場合...

真です。それ以外の場合はfalseです。

はObject.equals()(クラスを渡された場合)にのみ、基準等価性チェックstatic Equals() defined on object、又はvalue equalityために使用する(構造体を通過した場合)。

ので、要約で

string s1 = "t"; 
string s2 = 't'.ToString();   

Console.WriteLine(s1.Equals(s2)); // true because both reference equality (interned strings) and value equality (string overrides Equals()) 
Console.WriteLine(object.Equals(s1, s2)); // true because of reference equality (interned strings) 

StringBuilder s1 = new StringBuilder(); 
StringBuilder s2 = new StringBuilder(); 

Console.WriteLine(s1.Equals(s2)); // true because StringBuilder.Equals() overloaded 
Console.WriteLine(object.Equals(s1, s2)); // false because the two StringBuilder instances have different addresses (references not equal) 
+5

技術的には、StringBuilderは仮想オブジェクトをオーバーライドしないでEqualsメソッドをオーバーロードします。オブジェクト(オブジェクト)。これが、2つのメソッドが異なる振る舞いをする理由です。私は彼らがNET1.0でそれをするのを忘れていたのだろうか? – alexm

+0

@alexm:いいキャッチです。私は前にそれに気付かなかった。私の答えを更新しました。 –

+0

良い説明のためのタックエリック。私はそれから小さな要約を作る:object.Equalsは参照または値が入力オブジェクトの種類に依存するかどうかをチェックします。 StringとStringBuilderには、実装ごとに機能する独自のオーバーロード/オーバーライドEqualメソッドがあります。私が間違っているなら、私を修正してください。 –

1

generic Equals methodは、彼らがそのようなStringBuilderとして参照型のため参照平等を持っているかどうかを確認するために、2つのオブジェクトの参照を比較します。値型の場合、stringは値型のように動作します(不変です)。ビット単位の比較(バイナリ表現が同じかどうかを判断します)を行います。ただし、この機能はStringBuilderクラスでオーバーロードされます。

両方のStringBuilderオブジェクトに対して次の条件が等しい場合MSDNによれば、のStringBuilderの同じメソッドがtrueを返します。

  • ストリング
  • 容量
  • MAXCAPACITY

従って、S1が2番目の例のs2は参照の等価性に失敗しますが、前述の基準に基づいてカスタムStringBuilder Equalsの等価性を渡します。

+0

文字列は値型ではありません。 (値のセマンティクスを持つ参照型です)http://stackoverflow.com/questions/1069155/is-string-a-value-type-or-a-reference-type –

+0

@BradleyGrainger、私はそれがわからない技術的には値型ですが、この場合は同じ値として扱われます。私は明確にするために私の答えを更新します。ありがとう。 – Matt

1

文字列クラスの実装は、それが文字列の値を比較するように等しいです。

ほとんどのオブジェクトインスタンスは、異なるタイプの比較を実装しない限り、オブジェクトを参照しているかどうかをチェックします。

まったく同じ値を含む2つの異なる文字列定数が、最初はコンパイラによって同じオブジェクト参照に割り当てられることもあります。