== vs. Object.Equals(object) в .NET.
Итак, когда я был сравнительным новичком для новичков, я был прямо сейчас, я думал, что эти две вещи были синтаксическим сахаром друг для друга, то есть использование одного над другим было просто личным предпочтением. Со временем я пришел к выводу, что эти два не то же самое, даже в реализации по умолчанию (см. this и this). Чтобы еще больше смутить вопрос, каждый из них может быть переопределен/перегружен отдельно, чтобы иметь совершенно разные значения.
Это хорошая вещь, каковы различия, и когда/почему вы должны использовать один над другим?
Ответы
Ответ 1
MSDN имеет четкое и четкое описание обеих вещей.
object.Equals method
operator ==
Перегружаемые операторы
Рекомендации по переопределению равных() и операторов ==
Это хорошо, что такое различия, и когда/почему вы должны использовать один над другим?
Как это может быть "хорошо" или "плохо"? Один - метод, другой - оператор. Если ссылочного равенства недостаточно, перегрузите их, иначе оставьте их как есть. Для примитивных типов они просто работают из коробки.
Ответ 2
string x = "hello";
string y = String.Copy(x);
string z = "hello";
Проверить, если x
указывает на тот же объект, что и y
:
(object)x == (object)y // false
x.ReferenceEquals(y) // false
x.ReferenceEquals(z) // true (because x and z are both constants they
// will point to the same location in memory)
Чтобы проверить, имеет ли x
то же строковое значение, что и y
:
x == y // true
x == z // true
x.Equals(y) // true
y == "hello" // true
Обратите внимание, что это отличается от Java.
В Java оператор ==
не перегружен, поэтому распространенная ошибка в Java:
y == "hello" // false (y is not the same object as "hello")
Для сравнения строк в Java необходимо всегда использовать .equals()
y.equals("hello") // true
Ответ 3
Учитывая текущую инструкцию Microsoft о операторах равенства ==
и !=
, вывод следующий: ==
должен просто быть синтаксическим сахаром для Object.Equals()
:
Убедитесь, что Object.Equals и операторы равенства имеют точно такую же семантику
из http://msdn.microsoft.com/en-us/library/vstudio/7h9bszxx(v=vs.110).aspx
То, что они отличаются, а не просто сахаром, в ретроспективе, выглядит как ошибка в их дизайне.
Если вы хотите быть уверенным, что получаете сравнение ИДЕНТИФИКАЦИЯ (при сравнении ссылок), используйте вместо этого ReferenceEquals
.
К сожалению, обработка ==
настолько противоречива, что я обычно избегаю этого при манипулировании чужими пользовательскими классами и просто использую менее читаемые Equals(a, b)
или ReferenceEquals(a, b)
, в зависимости от того, какой смысл я хочу.
ИМХО, было бы лучше, если бы люди вообще не реализовали ==
и !=
. Просто укажите .Net по умолчанию Equals
и ! Equals
и внесите в него Equals
.
Если у кого-то разные рассуждения, я бы хотел это услышать.
(И да, это действительно сбивает с толку, учитывая, что Java существовала в первую очередь и использует ==
для обозначения ReferenceEquals
. Но слишком поздно менять .Net вести себя таким образом. И у нас есть собственное выражение Microsoft этот эффект в приведенной выше ссылке.)
Ответ 4
Я собирался опубликовать это как комментарий к принятому ответу, но я думаю, что это заслуживает рассмотрения при определении того, какой маршрут принять.
dotnetfiddle: https://dotnetfiddle.net/gESLzO
Код скрипта:
Object a = null;
Object b = new Object();
// Ex 1
Console.WriteLine(a == b);
// Ex 2
Console.WriteLine(b == a);
// Ex 3
Console.WriteLine(b.Equals(a));
// Ex 4
Console.WriteLine(a.Equals(b));
Первые 3 примера WriteLine будут работать, а четвертый - исключение. 1 и 2 используйте ==
, который является статическим методом, который не требует создания экземпляра объекта.
Пример 3 работает, потому что b
создается.
Пример 4 завершается с ошибкой, потому что a
есть null
, и поэтому метод не может быть вызван на нулевом объекте.
Поскольку я пытаюсь сделать код как можно более ленивым, я использую ==
, особенно при работе со сценариями, где любой объект (или оба) может быть нулевым. Если бы я этого не сделал, мне пришлось бы выполнить нулевую проверку, прежде чем можно было бы вызвать .Equals()
.
Ответ 5
Мое понимание использования обоих было следующим: use == для концептуального равенства (в контексте, эти два аргумента означают одно и то же?) и .Equals для конкретного равенства (эти два аргумента на самом деле точны тот же объект?).
Изменить: связанная статья Кевина Шеффилда лучше справляется с объяснением ценности и равенства ссылок...
Ответ 6
Возможно, вы захотите использовать .Equals, поскольку кто-то может прийти позже и перегрузить их для вас.
Ответ 7
Два из наиболее часто используемых типов, String и Int32, реализуют оба оператора ==() и Equals() как значение равенства (вместо ссылочного равенства). Я думаю, что можно рассмотреть эти два определения примеров, поэтому мой вывод состоит в том, что оба имеют одинаковые значения. Если Microsoft указывает в противном случае, я думаю, что они намеренно вызывают путаницу.
Ответ 8
Оператор == и Equals() оба одинаковы, а мы сравниваем значения вместо ссылок. Вывод обоих параметров аналогичен приведенному ниже примеру.
Пример
static void Main()
{
string x = " hello";
string y = " hello";
string z = string.Copy(x);
if (x == y)
{
Console.WriteLine("== Operator");
}
if(x.Equals(y))
{
Console.WriteLine("Equals() Function Call");
}
if (x == z)
{
Console.WriteLine("== Operator while coping a string to another.");
}
if (x.Equals(y))
{
Console.WriteLine("Equals() Function Call while coping a string to another.");
}
}
Вывод:
== Operator
Equals() Function Call
== Operator while coping a string to another.
Equals() Function Call while coping a string to another.