Вопрос

У меня есть условие в приложении silverlight, которое сравнивает 2 строки, по какой-то причине, когда я использую == он возвращается ложь в то время как .Equals() ВОЗВРАТ верно.

Вот этот код:

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
    // Execute code
}

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}

Есть какая-нибудь причина, почему это происходит?

Это было полезно?

Решение

Когда == используется для выражения типа object , оно преобразуется в System.Object.ReferenceEquals .

Equals - это всего лишь < code> virtual и ведет себя как таковой, поэтому будет использоваться переопределенная версия (которая для типа string сравнивает содержимое).

Другие советы

При сравнении ссылки на объект со строкой (даже если ссылка на объект ссылается на строку), специальное поведение оператора == , специфичное для класса строки, игнорируется.

Обычно (то есть, когда не работает со строками), Equals сравнивает значения , а == сравнивает ссылки на объекты . Если два сравниваемых объекта ссылаются на один и тот же точный экземпляр объекта, то оба будут возвращать true, но если один объект имеет одинаковое содержимое и поступил из другого источника (это отдельный экземпляр с одинаковыми данными), только Equals будет верните истину. Однако, как отмечено в комментариях, строка - это особый случай, поскольку она переопределяет оператор == , так что при работе исключительно со ссылками на строки (а не ссылками на объекты) сравниваются только значения, даже если они это отдельные экземпляры. Следующий код иллюстрирует тонкие различия в поведении:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

Вывод:

True True True
False True True
False False True

== и .Equals оба зависят от поведения, определенного в фактическом типе, и от фактического типа на сайте вызова.Оба являются просто методами / операторами, которые могут быть переопределены для любого типа и вести себя так, как пожелает автор.По моему опыту, я нахожу, что люди обычно внедряют .Equals на объекте, но пренебрегаете реализацией operator ==.Это означает , что .Equals будет фактически измерять равенство значений, в то время как == будет измерено, являются ли они одной и той же ссылкой.

Когда я работаю с новым типом, определение которого постоянно меняется, или пишу универсальные алгоритмы, я нахожу, что наилучшей практикой является следующее

  • Если я хочу сравнить ссылки на C #, я использую Object.ReferenceEquals непосредственно (не требуется в общем случае)
  • Если я хочу сравнить значения, я использую EqualityComparer<T>.Default

В некоторых случаях, когда я чувствую использование == является неоднозначным, я буду явно использовать Object.Reference равно в коде, чтобы устранить двусмысленность.

Эрик Липперт недавно опубликовал сообщение в блоге на тему того, почему в CLR существует 2 метода равенства.Это стоит того, чтобы прочесть

Во-первых, есть разница. Для номеров

> 2 == 2.0
True

> 2.Equals(2.0)
False

И для строк

> string x = null;
> x == null
True

> x.Equals(null)
NullReferenceException

В обоих случаях == ведет себя более полезно, чем .Equals

Я бы добавил, что если вы приведете ваш объект к строке, он будет работать правильно. Вот почему компилятор выдаст вам предупреждение:

  

Возможное непреднамеренное сравнение ссылок; чтобы получить сравнение значений,   приведите левую сторону к типу 'string'

== Оператор 1.Если операнды являются Типы значений и если их значения равны, он возвращает true, в противном случае false.2.Если операнды являются Ссылочные типы за исключением string, и оба ссылаются на один и тот же объект, он возвращает true, иначе false.3.Если операнды имеют строковый тип и их значения равны, он возвращает true, иначе false.

.Равно 1.Если операнды являются ссылочными типами, он выполняет Ссылочное равенство то есть, если оба ссылаются на один и тот же объект, это возвращает true, иначе false.2.Если операнды являются типами значений, то в отличие от оператора == он сначала проверяет их тип, и если их типы совпадают, он выполняет оператор ==, иначе он возвращает false.

Насколько я понимаю, ответ прост:

<Ол>
  • == сравнивает ссылки на объекты.
  • .Equals сравнивает содержимое объекта.
  • Строковые типы данных всегда действуют как сравнение содержимого.
  • Надеюсь, я прав и что он ответил на ваш вопрос.

    Поскольку статическая версия .Equal метод до сих пор не упоминался, я хотел бы добавить это здесь, чтобы подвести итог и сравнить 3 варианта.

    MyString.Equals("Somestring"))          //Method 1
    MyString == "Somestring"                //Method 2
    String.Equals("Somestring", MyString);  //Method 3 (static String.Equals method) - better
    

    где MyString это переменная, которая берется откуда-то еще в коде.

    Справочная информация и подведение итогов:

    В Java с использованием == для сравнения строк использоваться не следует.Я упоминаю об этом на случай, если вам нужно использовать оба языка, а также чтобы вы знали, что использование == также может быть заменен чем-то лучшим на C #.

    В C # нет практической разницы для сравнения строк с использованием Метода 1 или Метода 2, если оба имеют тип string.Однако, если единица равна null, единица имеет другой тип (например, целое число) или единица представляет объект, который имеет другую ссылку, то, как показывает первоначальный вопрос, вы можете столкнуться с тем, что сравнение содержимого на равенство может не вернуть то, что вы ожидаете.

    Предлагаемое решение:

    Потому что использование == это не совсем то же самое, что использовать .Equals сравнивая вещи, вы можете использовать статическая строка.Равна метод вместо этого.Таким образом, если две стороны не одного типа, вы все равно будете сравнивать содержимое, и если одна из них равна нулю, вы избежите исключения.

       bool areEqual = String.Equals("Somestring", MyString);  
    

    Это немного больше по написанию, но, на мой взгляд, безопаснее в использовании.

    Вот некоторая информация, скопированная из Microsoft:

    public static bool Equals (string a, string b);
    

    Параметры

    a Строка

    Первая строка для сравнения, или null.

    b Строка

    Вторая строка для сравнения, или null.

    ВОЗВРАТ Boolean

    true если значение a совпадает со значением b;в противном случае, false.Если оба a и b являются null, метод возвращает true.

    Я немного запутался здесь. Если тип времени выполнения Content имеет тип string, то оба == и Equals должны возвращать true. Однако, поскольку это не соответствует действительности, тип контента во время выполнения не является строкой, и вызов Equals для него делает ссылочное равенство, и это объясняет, почему Equals (" Energy Attack ") завершается неудачно. Однако во втором случае решение о том, какой перегруженный == статический оператор следует вызывать, принимается во время компиляции, и это решение выглядит как == (строка, строка). это говорит о том, что Content обеспечивает неявное преобразование в строку.

    Есть еще одно измерение в более раннем ответе @BlueMonkMN. Дополнительное измерение заключается в том, что ответ на заглавный вопрос @ Drahcir в том виде, в котором он сформулирован, также зависит от того, как мы достигли значения string . Для иллюстрации:

    string s1 = "test";
    string s2 = "test";
    string s3 = "test1".Substring(0, 4);
    object s4 = s3;
    string s5 = "te" + "st";
    object s6 = s5;
    Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
    
    Console.WriteLine("\n  Case1 - A method changes the value:");
    Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
    Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
    
    Console.WriteLine("\n  Case2 - Having only literals allows to arrive at a literal:");
    Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
    Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
    

    Вывод:

    True True True
    
      Case1 - A method changes the value:
    False True True
    False False True
    
      Case2 - Having only literals allows to arrive at a literal:
    True True True
    True True True
    

    Добавление еще одного пункта к ответу.

    Метод

    .EqualsTo () дает вам возможность сравнивать с культурой и чувствительностью к регистру.

    Так же, как дополнение к и без того хорошим ответам: это поведение НЕ ограничено строками или сравнением различных числовых типов. Даже если оба элемента имеют тип объекта одного и того же базового типа. & Quot; == & Quot; не сработает.

    На следующем снимке экрана показаны результаты сравнения двух объектных {int} - значений

     Пример из VS2017

    Тот Самый == токен в C # используется для двух разных операторов проверки равенства.Когда компилятор обнаруживает этот токен, он проверяет, реализовал ли какой-либо из сравниваемых типов перегрузку оператора равенства либо для конкретных сравниваемых комбинационных типов (*), либо для комбинации типов, в которые могут быть преобразованы оба типа.Если компилятор обнаружит такую перегрузку, он будет использовать ее.В противном случае, если оба типа являются ссылочными типами и они не являются несвязанными классами (либо могут быть интерфейсом, либо они могут быть связанными классами), компилятор будет учитывать == в качестве оператора сравнения ссылок.Если ни одно из условий не выполняется, компиляция завершится неудачей.

    Обратите внимание, что некоторые другие языки используют отдельные токены для двух операторов проверки равенства.В VB.NET, например, = токен используется в выражениях исключительно для перегружаемого оператора проверки равенства, и Is используется в качестве оператора эталонного теста или нулевого теста.Как использовать = для типа, который не переопределяет оператор проверки на равенство, произойдет сбой, как и попытка использовать Is для любых целей, отличных от проверки равенства ссылок или недействительности.

    (*) Типы обычно перегружают равенство только для сравнения с самими собой, но типам может быть полезно перегружать оператор равенства для сравнения с другими конкретными типами;например, int мог бы (и, ИМХО, должен был, но не сделал) определить операторы равенства для сравнения с float, так что 16777217 не сообщал бы о себе, равном 16777216f.Как бы то ни было, поскольку такой оператор не определен, C # будет продвигать int Для float, округляя его до 16777216f, прежде чем оператор проверки равенства увидит это;затем этот оператор видит два равных числа с плавающей запятой и сообщает о них как о равных, не подозревая о произошедшем округлении.

    Действительно отличные ответы и примеры!

    Я просто хотел бы добавить фундаментальную разницу между ними,

      

    Операторы, такие как == , не являются полиморфными, а Equals -

    Имея в виду эту концепцию, если вы отработаете какой-либо пример (взглянув на левый и правый ссылочный тип и проверив / узнав, действительно ли в типе перегружен оператор == и равнозначно ли равно), вы обязательно получите правильный ответ.

    Когда мы создаем какой-либо объект, объект состоит из двух частей, одна из которых является контентом, а другая - ссылкой на этот контент. == сравнивает и содержание, и ссылку; equals () сравнивает только содержимое

    http: // www. codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq

    ==

    Оператор == можно использовать для сравнения двух переменных любого типа, а он просто сравнивает биты .

    int a = 3;
    byte b = 3;
    if (a == b) { // true }
    

    Примечание: в левой части int больше нулей, но нас это не волнует.

    int a (00000011) == байт b (00000011)

    Помните == оператор заботится только о структуре битов в переменной.

    Использовать == Если две ссылки (примитивы) ссылаются на один и тот же объект в куче.

    Правила одинаковы, независимо от того, является ли переменная ссылочной или примитивной.

    Foo a = new Foo();
    Foo b = new Foo();
    Foo c = a;
    
    if (a == b) { // false }
    if (a == c) { // true }
    if (b == c) { // false }
    

    a == c верно a == b неверно

    битовые комбинации одинаковы для a и c, поэтому они равны, используя ==.

    Равно ():

    Используйте метод equals (), чтобы узнать, равны ли два разных объекта .

    Например, два разных объекта String, которые оба представляют символы в "Jane"

    Единственная разница между Equal и == заключается в сравнении типов объектов.в других случаях, таких как ссылочные типы и типы значений, они почти одинаковы (либо оба являются побитовым равенством, либо оба являются ссылочным равенством).

    объект:Равно:побитовое равенство ==:ссылочное равенство

    строка:(equals и == одинаковы для string, но если одна из строк изменена на object, то результат сравнения будет другим) Equals:побитовое равенство == :побитовое равенство

    Видишь здесь для получения дополнительных объяснений.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top