Равенство объектов ведет себя по-разному в .NET

У меня есть эти заявления и их & apos; результаты рядом с ними.

<code>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
</code>

Почему последнее равенство дает мне ложь?

Вопрос в том, почему (x == y) верно (k == m) неверно

 Anthony Pegram16 апр. 2012 г., 17:16
 Paolo Moretti16 апр. 2012 г., 17:22
После этого поста:When should I use == and when should I use Equals? k == m является ложным, потому что компилятор может вызывать только не перегруженную версию ==, поскольку он не знает, что содержимое c и d является строковыми ссылками. Поскольку они являются ссылками на разные строки, оператор идентификации возвращает false.
 Barış Velioğlu16 апр. 2012 г., 17:20
@AnthonyPegram На самом деле я не спрашиваю разницу между Equals и ==

Ответы на вопрос(9)

== оператор сравнивает ссылки (адреса памяти), в то время как .Equals сравнивает фактические значения объекта. В случае со строкой вам повезет, и две идентичные строки могут часто ссылаться на один и тот же адрес. Одна из радостей управляемых языков.

Потому что это две разные ссылки на объекты. Встроенное сравнение для этого - сравнить, указывают ли они на один и тот же фактический объект или нет.

Из-заString Interning, a а такжеb обе ссылки на один и тот же строковый объект.

c==d истина, потому что используется оператор равенства строк.

 16 апр. 2012 г., 17:11
После вашего ответа объясните почемуc == d?
Решение Вопроса

Как видно наC # FAQ по MSDN - компилятор не может использовать перегруженный метод и возвращается к сравнению ссылок.

Большой вопрос, почему это удается в первом сравнении объектов. Мое лучшее предположение, что это удается, потому что a и b оба имеют одинаковые ссылки. Для c и d вы заставляете разные ссылки.

Опираясь на 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() когда сравнение значений является желаемым?

Решение Вопроса
string a = "abc"; 
string b = "abc"; 

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

Строковые ссылки одинаковы для одной и той же строки из-заString Interning

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 

.Equals использует перегруженную строкуequals метод, который снова сравнивают по значению

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

Здесь мы проверяем, совпадают ли две ссылки ... они не

Ключ выясняет, когда равенство сравнивает ссылки или значения.

Объекты, если иное не перегружено, сравнивают ссылки.

Структуры, если иное не перегружено, сравнивают значения.

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

В случае строк,== оператор перегружен для проверки на равенство значений при использованииobject ссылочное равенство используется.

посколькуc а такжеd are строки, когда вы используетеEquals вk а такжеm, перегруженный метод используется.

А такжеc == d являетсяtrue по причине причины выше - значение равенства используется наstring типы как оператор перегружен.

 16 апр. 2012 г., 17:24
@Oded, интернирование строк применяется кstring литералы. Струныc а такжеd не используйте интернированные строки, потому что они не созданы из литералов.
 Barış Velioğlu16 апр. 2012 г., 17:15
На самом деле проблема в том, что если (k == m) неверно, почему (x == y) верно?
 16 апр. 2012 г., 17:15
@Nick - Как вы уже писали, за интернирование строк отвечает :)
 16 апр. 2012 г., 17:16
@Ryu - Если это то, что ты хотел спросить, то почему нет?
 16 апр. 2012 г., 17:14
Как насчет (х == у)

Когда ты сказалstring1 == string2сравнение используетstring тип перегружен== оператор, который сравнивает строки & apos; ценности.

Когда ты сказалobject1 == object2даже если в этом случае они являются строками, они не будут считаться строками для целей поиска оператора. Таким образом, сравнение использует по умолчанию== оператор, который сравниваетreferences для равенства. Это означает, что, если два объекта не являются одним и тем же объектом, он вернет false.

   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 Инструкция, которая делает сравнение значений равенства помещается в стек. Значения, помещенные в стекreferences как в штучной упаковке строки, которыеnot равны.

Ваш ответ на вопрос