== или .Equals () - PullRequest
       47

== или .Equals ()

56 голосов
/ 28 сентября 2008

Зачем использовать один над другим?

Ответы [ 12 ]

56 голосов
/ 28 сентября 2008

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

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

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


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


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

20 голосов
/ 28 сентября 2008

@ Джон Милликин:

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

Для уточнения:

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

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

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

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

15 голосов
/ 28 сентября 2008

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

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

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

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

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

6 голосов
/ 28 сентября 2008

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

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

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

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

3 голосов
/ 02 октября 2012

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

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

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

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

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
    }
}
2 голосов
/ 28 сентября 2008

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

2 голосов
/ 28 сентября 2008

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

2 голосов
/ 28 сентября 2008

Согласно MSDN :

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

...

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

1 голос
/ 18 декабря 2017

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

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

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

1 голос
/ 16 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...