Разница между Object.Equals(objA, objB), objA.Equals(objB) и objA == objB для типов CLR?
Мне интересно, будут ли типы CLR возвращать разные результаты из следующих:
Object.Equals(objA, objB)
objA.Equals(objB)
(objA == objB)
Я понимаю, что за пределами CLR кто-то может легко реализовать IEqualtable
Равно и перегружает оператор == неправильно. Я не беспокоюсь о людях, которые неправильно их реализуют. Я согласен с тем, что классы (включая String, Int32 и т. Д.) Реализуют эти 3 по-разному.
Кроме того, какой из них должен использоваться для общего сравнения (по всем направлениям), если это возможно. Мне интересно, потому что я наткнулся на файл, который использует Object.Equals(objA, objB)
по всей модели представления вместо двух других.
private string _name;
public string Name
{
get { return _name; }
set
{
if (Equals(_name, value)) return;
...
}
}
private int _id;
public int Id
{
get { return _id; }
set
{
if (Equals(_id, value)) return;
...
}
}
private Object _obj;
public Object TheObject
{
get { return _obj; }
set
{
if (Equals(_obj, value)) return;
...
}
}
2 ответа
Object.Equals(a,b) абсолютно безопасен. Он может отвечать, например, Equals (null, null), что верно. Кроме того, он просто вызывает обычный метод Equals (). Насколько я знаю, для строковых и примитивных типов clr определены операторы равенства, которые работают точно так же, как Object.Equals(a,b).
Для ненулевых objA и objB Object.Equals(objA, objB), objA.Equals(objB) и objB.Equals(objA) должны быть эквивалентны, если метод Equals реализован правильно.
Использование Equals(_obj, value) кажется правильным в размещенном вами коде.
Если вам нужен полный список сравнений на равенство, не забывайте об objA.ReferenceEquals(objB), который является своего рода равенством, которое полезно во многих сценариях.
Для любого числа с плавающей запятой Equals
а также ==
вести себя по-другому.
NaN==NaN => false
следуя логике IEEENaN.Equals(NaN) => true
Выполнение требования о том, что все должно быть равным себе.
И конечно Equals
переопределяется, т.е. работает даже тогда, когда статический тип является базовым, тогда как ==
перегружен и работает, только если статический тип был перегружен.
Я почти никогда не звоню x.Equals(y)
непосредственно. Для одного это не справиться с x
являющийся null
И асимметрия уродливая ИМО. Статический object.Equals(x,y)
вызывает виртуальный object.Equals(y)
метод, но добавляет нулевую обработку.
IEquatable<T>.Equals(other)
эквивалентно object.Equals(other)
на все типы с хорошим поведением, но это избегает бокса в типах значений.
В заключение я обычно предпочитаю ==
когда статический тип известен, и EqualityComparer<T>.Default
с универсальными типами или если статический тип не соответствует типу времени выполнения.
В вашем примере Name
а также Id
вести себя так же с ==
а также Equals
, поскольку string
а также int
запечатаны
TheObject
с другой стороны, проявляет другое поведение с ==
а также Equals
для определенных типов. Например, если вы используете string
затем Equals
будет использовать равенство значений, и ==
будет использовать ссылочное равенство.