2008-09-27 3 views
54

Зачем использовать один над другим?== or .Equals()

+7

Замечание для тех, кто ищет и находит этот ответ, может быть перегружен как «Равно», так и «==», поэтому точные результаты вызова одного или другого будут разными. Например, `string` выполняет тест равенства для` == `. Также обратите внимание, что семантика обоих может быть [сложной] (http://blogs.msdn.com/b/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx). – Guvante 2012-10-01 19:58:47

+0

Возможный дубликат [C# разница между \ `== \` и .Equals()] (http://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) – 2013-08-26 22:26:13

+0

Согласно Microsoft Framework Рекомендации по дизайну: «Убедитесь, что Object.Equals и операторы равенства имеют точно такую ​​же семантику и аналогичные характеристики производительности». https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators – 2017-12-18 15:39:16

ответ

54

== Тест идентичности. Он вернет true, если два тестируемых объекта фактически являются одним и тем же объектом. Equals() выполняет тест равенства и возвращает true, если оба объекта считают себя равными.

Идентификация выполняется быстрее, поэтому вы можете использовать ее, когда нет необходимости в более дорогих тестах на равенство. Например, сравнивая с null или пустой строкой.

Можно перегрузить любой из них, чтобы обеспечить различное поведение - например, тестирование идентичности для Equals() - но для того, чтобы кто-либо читал ваш код, не делайте этого.


Указано ниже: некоторые типы как String или DateTime обеспечивают перегрузку для == оператора, которые дают ему семантику равенства. Точное поведение будет зависеть от типов объектов, которые вы сравниваете.


Смотрите также:

+0

Как бы вы перегрузили ==? Из любопытства. – Brettski 2008-09-27 21:42:22

+1

@ Бретт: понятия не имею, но блог MSDN говорит, что это возможно. – 2008-09-27 21:43:07

1

использование равно, если вы хотите, чтобы выразить содержание объектов по сравнению должны быть равны. используйте == для примитивных значений или если вы хотите проверить, что сравниваемые объекты - это один и тот же объект. Для объектов == проверяет, является ли адресный указатель объектов одинаковым.

6

== Как правило, «идентичность» означает значение «объект a на самом деле является тем же самым объектом в памяти, что и объект b».

equals() означает, что объекты логически равны (скажем, с бизнес-точки зрения). Поэтому, если вы сравниваете экземпляры определенного пользователем класса, вам обычно нужно использовать и определять equals(), если вы хотите, чтобы такие вещи, как Hashtable, работали правильно.

Если у вас был класс пословиц Person со свойствами «Имя» и «Адрес», и вы хотели использовать этого Лица в качестве ключа в Hashtable, содержащем больше информации о них, вам необходимо реализовать equals() (и хеш), чтобы вы могли создать экземпляр Person и использовать его в качестве ключа в Hashtable для получения информации.

Используя только один, ваш новый экземпляр будет не быть таким же.

2

В соответствии с MSDN:

В C#, существует два различных типа равенства: равенство ссылок (также известные как идентичность) и равенство значений. Ценностное равенство - это общепринятое значение равенства: это означает, что два объекта содержат одни и те же значения. Например, два целых числа со значением 2 имеют значение равенства. Ссылочное равенство означает, что не существует двух объектов для сравнения. Вместо этого есть две ссылки на объекты, и оба они относятся к одному и тому же объекту.

...

По умолчанию оператор == тесты на равенство ссылок, определяя две ссылки указывают ли один и тот же объект.

2

Пример состоит в том, что класс DateTime реализует интерфейс IEquatable, который реализует «специфичный для типа метод определения равенства экземпляров». согласно MSDN.

2

Другая вещь, которую следует учитывать: оператор == может не быть вызываемым или может иметь разное значение, если вы обращаетесь к объекту с другого языка. Обычно лучше иметь альтернативу, которую можно назвать по имени.

12

Всем остальным в значительной степени охвачены, но у меня есть еще одно слово совета. Время от времени вы получаете кого-то, кто клянется в своей жизни (и своих близких), что. Эвкалы более эффективны/лучше/лучше всего или в какой-то другой догматической линии. Я не могу говорить об эффективности (хорошо, хорошо, в определенных обстоятельствах я могу), но я могу поговорить с большой проблемой, которая возникнет: .Equals требует существования объекта. (Звучит глупо, но это бросает человек с.)

Вы не можете сделать следующее:

StringBuilder sb = null; 
if (sb.Equals(null)) 
{ 
    // whatever 
} 

Это кажется очевидным для меня, и, возможно, большинство людей, что вы получите NullReferenceException. Однако сторонники Эвальского языка забывают об этом маленьком фактоиде. Некоторые даже «отбрасываются» (извините, не могут удержаться), когда они видят, что NullRefs начинают всплывать.

(И лет до DailyWTF размещения, я на самом деле работать с кем-то, кто подмандатной, что все проверки равенства быть .equals вместо ==. Даже доказав его неточность не помогло. Мы просто сделали чертовски уверен сломать все его другие правила, так что ссылка не возвратившиеся из метода, ни свойство было когда-либо нулевой, и он работал, в конце концов)

20

@John Милликин:.

Указано ниже: некоторые типы значений как DateTime обеспечивают перегрузки для оператора ==, которые дают ему семантику равенства. Точное поведение будет зависеть от типов объектов, которые вы сравниваете.

Выработать:

DateTime реализован в виде структуры. Все структуры являются дочерними элементами System.ValueType.

Поскольку дети System.ValueType живут в стеке, нет указателя ссылки на кучу и, следовательно, нет способа выполнить контрольную проверку, вы должны сравнивать объекты только по значению.

System.ValueType переопределяет .Equals() и == использовать проверку равенства на основе отражения, использует отражение для сравнения значения каждого поля.

Поскольку отражение происходит несколько медленно, если вы реализуете свою собственную структуру, важно переопределить .Equals() и добавить свой собственный код проверки значения, поскольку это будет намного быстрее. Не просто вызвать base.Equals();

1

Я видел Object.ReferenceEquals(), используемый в тех случаях, когда один хочет знать, если две ссылок относятся к одному объекту

2

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

Например, string выполняет проверку равенства для ==.

Также обратите внимание, что семантика обоих может быть complex.

Лучшей практикой является реализация равенства, подобного этому примеру. Обратите внимание, что вы можете упростить или исключить все это, в зависимости от того, как вы планируете использовать ваш класс, и что это можно сделать уже с нуля.

class ClassName 
{ 
    public bool Equals(ClassName other) 
    { 
     if (other == null) 
     { 
      return false; 
     } 
     else 
     { 
      //Do your equality test here. 
     } 
    } 

    public override bool Equals(object obj) 
    { 
     ClassName other = obj as null; //Null and non-ClassName objects will both become null 
     if (obj == null) 
     { 
      return false; 
     } 
     else 
     { 
      return Equals(other); 
     } 
    } 

    public bool operator ==(ClassName left, ClassName right) 
    { 
     if (left == null) 
     { 
      return right == null; 
     } 
     else 
     { 
      return left.Equals(right); 
     } 
    } 

    public bool operator !=(ClassName left, ClassName right) 
    { 
     if (left == null) 
     { 
      return right != null; 
     } 
     else 
     { 
      return !left.Equals(right); 
     } 
    } 

    public override int GetHashCode() 
    { 
     //Return something useful here, typically all members shifted or XORed together works 
    } 
} 
0

Если разобрать (по dotPeek, например) объекта, так

public virtual bool Equals(Object obj) 

описано как:

// Returns a boolean indicating if the passed in object obj is 
// Equal to this. Equality is defined as object equality for reference 
// types and bitwise equality for value types using a loader trick to 
// replace Equals with EqualsValue for value types). 
// 

Итак, это зависит от типа. Например:

 Object o1 = "vvv"; 
     Object o2 = "vvv"; 
     bool b = o1.Equals(o2); 

     o1 = 555; 
     o2 = 555; 
     b = o1.Equals(o2); 

     o1 = new List<int> { 1, 2, 3 }; 
     o2 = new List<int> { 1, 2, 3 }; 
     b = o1.Equals(o2); 

Первый раз б истинно (равно выполняется на типы значений), второй раз б истинно (равно выполняется на типы значений), в третий раз б ложно (равно выполняется на ссылочных типов).

0

В большинстве случаев они одинаковы, поэтому для ясности следует использовать ==. В соответствии с Руководством по разработке Microsoft Framework:

«DO убедитесь, что Object.Equals и операторы равенства имеют точно такую ​​же семантику и аналогичные характеристики производительности». https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators

Но иногда кто-то переопределяет Object.Equals без предоставления операторов равенства. В этом случае вы должны использовать Equals для проверки равенства значений и Object.ReferenceEquals для проверки ссылочного равенства.

Смежные вопросы