Разность C # между == и Equals ()

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

Вот код:

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

Любая причина, почему это происходит?

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

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

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

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

 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 реализуют .Equals на объекте, но пренебрегают внедрением operator == . Это означает, что .Equals будет фактически измерять равенство значений, а == будет измерять, являются ли они одной и той же ссылкой.

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

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

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

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

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

 > 2 == 2.0 True > 2.Equals(2.0) False 

И для строк

 > string x = null; > x == null True > x.Equals(null) NullReferenceException 

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

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

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

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

.equals 1. Если операнды ссылочные типы, она выполняет равенство ссылок , то есть если оба относятся к тому же объекту, он возвращает истину еще ложь. 2. Если Операнды – это типы значений, то в отличие от оператора == он сначала проверяет их тип, и если их типы одинаковы, он выполняет == operator else, он возвращает false.

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

  1. == сравнивает ссылки на объекты.
  2. .Equals сравнивает содержимое объекта.
  3. String datatypes всегда действуют как сравнение контента.

Надеюсь, я прав, и это ответ на ваш вопрос.

Я немного смущен. Если тип содержимого времени выполнения имеет строку типа, то оба == и 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() дает вам возможность сравнивать с культурой и чувствительностью к регистру.

Поскольку статическая версия метода .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, если оба имеют строку типа. Однако, если один из них является нулевым, один имеет другой тип (например, целое число) или один представляет объект, который имеет другую ссылку, то, как показывает первоначальный вопрос, может возникнуть впечатление, что сравнение содержимого для равенства может не вернуть вы ожидаете.

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

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

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

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

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

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

параметры

строка

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

b Строка

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

Возвращает Boolean

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

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

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

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

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

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

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

С учетом этой концепции, если вы выработаете какой-либо пример (посмотрев на ссылочный тип левой руки и правой руки и проверив / зная, действительно ли тип перегружен оператором ==, а 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 больше нhive, но здесь нас это не волнует.

int a (00000011) == byte 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 и == заключается в сравнении типов объектов. в других случаях, таких как ссылочные типы и типы значений, они почти одинаковы (либо оба являются поразрядным равенством, либо оба являются ссылочным равенством).

object: Equals: bit-wise равенство ==: ссылочное равенство

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

Подробнее см. Здесь .

  • Любые причины, чтобы предпочесть getClass () над instanceof при генерации .equals ()?
  • Как переопределить метод equals в java
  • Использование '==' вместо .equals для строк Java
  • Сравнивая две строки, игнорируя регистр в c #
  • Лучшая реализация для метода hashCode
  • Почему нам нужно переопределить метод equals () в Java?
  • Разница между пустой и пустой ("") строкой Java
  • В чем разница между IEquatable и просто переопределением Object.Equals ()?
  • Это плохая идея, если equals (null) вместо NullPointerException выбрасывает?
  • Как проверить, равна ли моя строка нулевой?
  • Hashcode и Equals для Hashset
  • Interesting Posts

    Что такое «область» в базовой аутентификации

    Сообщение для входа в Facebook: «URL Blocked: эта переадресация не удалась, потому что URI перенаправления не включен в настройки клиента OAuth».

    Сравнение равенств между несколькими переменными

    Очистить stdin перед чтением

    Браузеры игнорируют файл hosts

    Может ли JavaScriptSerializer исключать свойства с нулевыми значениями / значениями по умолчанию?

    Введите имя столбца в data.table с помощью переменной

    Профайлинг Windows XP?

    Добавить водосточный желоб (привязка) к существующему файлу PDF

    Как открыть проект Android Studio в Eclipse?

    Ошибка манифеста слияния с несколькими ошибками в Android Studio

    Android: переключение камеры при нажатии кнопки

    Как получить таблицу строк «один ко многим» путем слияния дублированных ячеек в большой нормализованной таблице?

    Как я могу получить событие в Android Spinner, когда выбранный выбранный элемент снова выбран?

    Как выполнить сравнение подстановочных строк в пакетном файле

    Давайте будем гением компьютера.