CA2218: переопределяйте GetHashCode при переопределении Equals
TypeName |
OverrideGetHashCodeOnOverridingEquals |
CheckId |
CA2218 |
Категория |
Microsoft.Usage |
Критическое изменение |
Не критическое |
Причина
Открытый тип переопределяет Object.Equals, но не переопределяет Object.GetHashCode.
Описание правила
GetHashCode возвращает значение на основе текущего экземпляра, используемое для алгоритмов хэширования и структур данных, таких как таблица хэша.Два равных друг другу объекта одинакового типа должны возвращать одинаковый код хэша, чтобы экземпляры следующих типов правильно работали:
Dictionary
SortDictionary
SortList
HybredDictionary
Типы, реализующие IEqualityComparer.
Устранение нарушений
Чтобы устранить нарушение данного правила, предоставьте реализацию GetHashCode.Для пары объектов одинакового типа реализация должна возвращать одинаковое значение, если реализация Equals возвращает true для этой пары.
Отключение предупреждений
Для этого правила отключать вывод предупреждений не следует.
Пример класса
Описание
В следующем примере демонстрируется класс (ссылочный тип), нарушающий это правило.
Код
using System;
namespace Samples
{
// Violates this rule
public class Point
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (GetType() != obj.GetType())
return false;
Point point = (Point)obj;
if (_X != point.X)
return false;
return _Y == point.Y;
}
}
}
Комментарии
В следующем примере нарушение устраняется путем переопределения GetHashCode.
Код
using System;
namespace Samples
{
public struct Point : IEquatable<Point>
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override int GetHashCode()
{
return _X ^ _Y;
}
public override bool Equals(object obj)
{
if (!(obj is Point))
return false;
return Equals((Point)obj);
}
public bool Equals(Point other)
{
if (_X != other._X)
return false;
return _Y == other._Y;
}
public static bool operator ==(Point point1, Point point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Point point1, Point point2)
{
return !point1.Equals(point2);
}
}
}
Пример структуры
Описание
В следующем примере показана структура (тип значения), нарушающая это правило.
Код
using System;
namespace Samples
{
// Violates this rule
public struct Point : IEquatable<Point>
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override bool Equals(object obj)
{
if (!(obj is Point))
return false;
return Equals((Point)obj);
}
public bool Equals(Point other)
{
if (_X != other._X)
return false;
return _Y == other._Y;
}
public static bool operator ==(Point point1, Point point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Point point1, Point point2)
{
return !point1.Equals(point2);
}
}
}
Комментарии
В следующем примере нарушение устраняется путем переопределения GetHashCode.
Код
using System;
namespace Samples
{
public struct Point : IEquatable<Point>
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override int GetHashCode()
{
return _X ^ _Y;
}
public override bool Equals(object obj)
{
if (!(obj is Point))
return false;
return Equals((Point)obj);
}
public bool Equals(Point other)
{
if (_X != other._X)
return false;
return _Y == other._Y;
}
public static bool operator ==(Point point1, Point point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Point point1, Point point2)
{
return !point1.Equals(point2);
}
}
}
Связанные правила
CA1046: не перегружайте оператор равенства для ссылочных типов
CA2225: для перезагрузок оператора существуют дополнения с именами
CA2226: перегрузки операторов должны быть симметричны
CA2224: переопределяйте равенство при перегрузке оператора равенства
CA2231: перегружать равенство операторов следует при перегрузке ValueType.Equals
См. также
Ссылки
Другие ресурсы
Guidelines for Implementing Equals and the Equality Operator (==)