Similar presentations:
Equals. Метод Ecuals
1. Equals
Виртуальные методыEquals
GetHashCode
2. Метод Ecuals
Виртуальный метод Equals определен в типе System.Object идоступен всем типам.
Метод Equals() проверяет два объекта на равенство и
возвращает true, если оба объекта равны;
Сигнатура метода: bool Object.Equals(Object value);
public static void Main(string[] args)
{
object x = 5;
object y = 5;
Console.WriteLine(x.Equals(y)); //true
}
3. Поведение метода Equals по умолчанию:
Для ссылочных типов -> true, если ссылки совпадают.Для значимых типов -> true, если совпадают тип и значение.
string - это особый случай. Он ведет себя как тип значения.
Для структур – эквивалентность для каждого поля.
Объект равный null, выбросит исключение
NullReferenceException;
Метод можно переопределить или реализовать один из
подходящих интерфейсов.
4. Реализация метода Equals:
public virtual bool Equals(object other){
var this.Ref = GetReference(this);
var other.Ref = GetReference(other);
if (this.Ref == other.Ref)
{
return true;
}
return false;
}
5. Основные причины для переопределения метода Equals для своего типа:
Основные причины для переопределенияметода Equals для своего типа:
Изменение семантики эквивалентности;
Ускорение процесса сравнения структур.
public virtual bool Equals(object obj);
возвращает true, если параметр и вызывающий объект
ссылаются на одну и туже область памяти;
public static bool Equals(object ob1, object ob2);
возвращает true, если оба параметра ссылаются на одну и ту
же область памяти;
6. Правила переопределения метода Equals :
Правила переопределения метода Equals :Сравнение с null: объект не может быть равен null (за
исключением Nullable типов)
x.Equals(null) == false;
Рефлексивно:
x.Equals(x) == true;
Симметрично: реализация должна быть коммутативной,
если a.Equals(b) ==true, то b.Equals(a) == true;
Транзитивно:
a.Equals(b) == true,
b.Equals(c) ==true ,
a.Equals(c) == true;
Согласовано: метод должен быть повторяем и надежен.
7. Пример переопределения метода Equals
// сравнение значений, а не ссылокpublic override bool Equals( object obj )
{
if ( obj == null || GetType() != obj.GetType() )
return false;
Monster temp = (Monster) obj;
return health == temp.health &&
ammo == temp.ammo &&
name == temp.name;
}
public override int GetHashCode()
{
return name.GetHashCode();
}
8. Метод GetHashCode
Является виртуальным методом типа object.Используется в двух коллекциях:
System.Collections.Hashtable
System.Collections.Generic.Dictionary<TKey,TValue>
Возвращает значение хеш-функции объекта, который может
использоваться в алгоритмах хэширования и хэш-таблицах.
Хэш-код - целое знаковое 32 битное число.
9. Метод GetHashCode
В ссылочных и значимых типах имеют стандартную реализациюметода.
Для хэш-функции должны использоваться только те поля,
которые используются в Equals методе.
Метод переопределяется в случае, если переопределяется
Equals() (необходимо для корректной работы с объектами
класса Hashtable (Хэш-таблица).
10. Алгоритм работы метода GetHashCode
public (bool, TValue) Get(TKey key){
var hashCode = key.GetHashCode();
var index = Math.Abs(hashCode % _storageSize);
var values = _storage[index];
for (var i = 0; i < values.Length; ++i)
{
var (storedKey, value) = values[i];
if (storedKey.Equals(key))
{
return (true, value);
}
}
return (false, default);
}
11. Пример реализации метода GetHashCode
class Person{
public string Name { get; set; } = "";
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
public virtual int GetHashCode()
{
if (_hashCode)
return _hashCode;
_hashCode = GenerateNewHashCode(_threadId);
return _hashCode;
}
12. Правила переопределения метода GetHashCode:
Совместимо с 'Equals‘: должен возвращаться одинаковый хэшкод длялюбых двух объектов, для которых вызов Equals возвращает true;
Не должен генерировать исключение.
Должен возвращаться одинаковый хэш-код для одного и того же
объекта вне зависимости от количества вызовов метода GetHashCode ;
Необходимо минимизировать вероятность возвращения одного и того
же хэш-кода для двух различных объектов (для получения
максимальной производительности).
Всегда необходимо переопределять Equals и GetHashCode, чтобы
избежать снижения производительности.