6

私はこれらの声明を持っています、そして彼らの結果はそれらの近くにあります。

string a = "abc";
string b = "abc";

Console.Writeline(a == b); //true

object x = a;
object y = b;

Console.Writeline(x == y); // true

string c = new string(new char[] {'a','b','c'});
string d = new string(new char[] {'a','b','c'});

Console.Writeline(c == d); // true

object k = c;
object m = d;

Console.Writeline(k.Equals(m)) //true

Console.Writeline(k == m); // false

なぜ最後の平等は私に偽を与えるのですか?

問題は、(x == y)が真(k == m)が偽である理由です。

4

9 に答える 9

10

文字列の場合、参照の同等性を使用すると、==演算子は値の同等性をテストするためにオーバーロードされます。object

cd 文字列であるため、とで使用する場合は、Equalsオーバーロードされたメソッドが使用されます。km

そして、上記の理由のためc == dです-演算子がオーバーロードされると、型trueに値の等式が使用されます。string

于 2012-04-16T15:12:45.347 に答える
9
string a = "abc"; 
string b = "abc"; 

Console.Writeline(a == b); //true 

文字列インターニングにより、同じ文字列の文字列参照は同じです

object x = a; 
object y = b; 

Console.Writeline(x == y); // true 

参照は同じであるため、同じ参照から作成された2つのオブジェクトも同じです。

string c = new string(new char[] {'a','b','c'}); 
string d = new string(new char[] {'a','b','c'}); 

ここでは、2つの新しい文字配列を作成しますが、これらの参照は異なります。

Console.Writeline(c == d); // true 

文字列は、値で比較するために==をオーバーロードしました。

object k = c; 
object m = d; 

以前の参照が異なるため、これらのオブジェクトは異なります。

Console.Writeline(k.Equals(m)) //true 

.EqualsオーバーロードされたStringequalsメソッドを使用します。これも値で比較されます

Console.Writeline(k == m); // false 

ここでは、2つの参照が同じであるかどうかを確認します...そうではありません

重要なのは、平等が参照または値を比較しているときを把握することです。

オブジェクトは、特にオーバーロードされていない限り、参照を比較します。

構造体は、特にオーバーロードされていない限り、値を比較します。

于 2012-04-16T15:24:36.277 に答える
3

それらは2つの異なるオブジェクト参照であるためです。このための組み込みの比較は、それらが同じ実際のオブジェクトを指しているかどうかを比較することです。

文字列インターニングが原因でabは両方とも同じ文字列オブジェクトへの参照です。

c==d文字列の等式演算子が使用されているため、trueです。

于 2012-04-16T15:11:10.647 に答える
2
   string c = new string(new char[] {'a','b','c'});
   string d = new string(new char[] {'a','b','c'});

   Console.WriteLine(c == d); // true

   object k = c;
   object m = d;

   Console.WriteLine(k.Equals(m)); //true

   Console.WriteLine(k == m); // false

次のようなILコードを生成します。

IL_0001:  ldc.i4.3    
IL_0002:  newarr      System.Char
IL_0007:  dup         
IL_0008:  ldtoken     <PrivateImplementationDetails>{61BB33F4-0CA5-4733-B259-764124AD1A79}.$$method0x6000002-1
IL_000D:  call        System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
IL_0012:  newobj      System.String..ctor
IL_0017:  stloc.0     
IL_0018:  ldc.i4.3    
IL_0019:  newarr      System.Char
IL_001E:  dup         
IL_001F:  ldtoken     <PrivateImplementationDetails>{61BB33F4-0CA5-4733-B259-764124AD1A79}.$$method0x6000002-2
IL_0024:  call        System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
IL_0029:  newobj      System.String..ctor
IL_002E:  stloc.1     
IL_002F:  ldloc.0     
IL_0030:  ldloc.1     
IL_0031:  call        System.String.op_Equality   //STRING EQUALITY 
IL_0036:  call        System.Console.WriteLine
IL_003B:  nop         
IL_003C:  ldloc.0     
IL_003D:  stloc.2     
IL_003E:  ldloc.1     
IL_003F:  stloc.3     
IL_0040:  ldloc.2     
IL_0041:  ldloc.3     
IL_0042:  callvirt    System.Object.Equals
IL_0047:  call        System.Console.WriteLine
IL_004C:  nop         
IL_004D:  ldloc.2     
IL_004E:  ldloc.3     
IL_004F:  ceq         //CEQ INSTRUCTION: **VALUES** EQUALITY !
IL_0051:  call        System.Console.WriteLine

ご覧のとおり、最後の命令は、スタックにプッシュされた値の同等性の比較を行うCEQ命令を呼び出します。スタックにプッシュされた値は、両方のボックス化された文字列の参照であり、等しくありません。

于 2012-04-16T15:29:10.293 に答える
1

MSDNのC#FAQに見られるように、コンパイラはオーバーロードされたメソッドを使用できず、参照の比較にフォールバックします。

より大きな問題は、なぜ最初のオブジェクト比較に成功するのかということです。私の最善の推測は、aとbの両方に同じ参照が与えられているため、成功するということです。cとdの場合、異なる参照を強制しています。

于 2012-04-16T15:30:56.710 に答える
1

String==値の比較に使用できるように、等式演算子をオーバーロードしました。したがって、

a == b //true

それらをオブジェクトにダウンキャストするときは、参照を比較するだけです。 別の文字列インスタンスがすでに使用可能な場合はString内部文字列プールを調べます。それ以外の場合は、新しいインスタンスが作成されてプールに追加されます。したがって、実際aにはb、、、xおよびyは同じ参照でさえあります。そのためです。

x == y //true

のコンストラクターを使用するStringと、同じ値(長さと文字シーケンス)を持つ別の文字列が存在する場合でも、.NETに新しいインスタンスを作成させることになります。それが理由です

k == m //false

http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool

于 2012-04-16T15:32:28.123 に答える
1

と言うstring1 == string2と、比較では、文字列の値を比較するstring型のオーバーロード==演算子が使用されます。

と言うとobject1 == object2、この場合は文字列ですが、演算子を見つけるための文字列としての資格はありません。したがって、比較ではデフォルトの演算子を使用します。デフォルトの==演算子は、参照が等しいかどうかを比較します。つまり、2つのオブジェクトがまったく同じオブジェクトでない場合は、falseが返されます。

于 2012-04-16T15:13:34.393 に答える
1

Bob2Chivに基づいて、VB(VS2010)で同等のものを試しました。

    Dim a As String = "abc"
    Dim b As String = "abc"

    Console.WriteLine(a = b) ' True

    Dim x As Object = a
    Dim y As Object = b

    Console.WriteLine(x = y) ' True

    Dim c As String = New String(New Char() {"a"c, "b"c, "c"c})
    Dim d As String = New String(New Char() {"a"c, "b"c, "c"c})

    Console.WriteLine(c = d) ' True

    Dim k As Object = c
    Dim m As Object = d

    Console.WriteLine(k.Equals(m)) ' True

    Console.WriteLine(k = m) ' True (Yes, True!!)

    Console.WriteLine(k Is m) ' False (Like in C#)

    Console.WriteLine(a Is b) ' True (Like in C#)

(少なくとも、それは同等だと思います-これについて修正されることを歓迎します。)

道徳?:==C#では注意してください-.Equals()値の比較が望ましい場合に優先しますか?

于 2012-04-17T18:12:35.220 に答える
0

演算子は==参照(メモリアドレス)を比較し、.Equalsは実際のオブジェクト値を比較します。文字列の場合、幸運に恵まれ、2つの同じ文字列が同じアドレスを頻繁に参照する可能性があります。管理された言語の喜びの1つ。

于 2014-07-17T21:09:38.317 に答える