CA2218: переопределяйте GetHashCode при переопределении Equals
Товар | Значение |
---|---|
Идентификатор правила | CA2218 |
Категория | Microsoft.Usage |
Критическое изменение | Не критическое |
Причина
Открытый тип переопределяет System.Object.Equals, но не System.Object.GetHashCode.
Описание правила
GetHashCode возвращает значение, основанное на текущем экземпляре, которое подходит для хэширования алгоритмов и структур данных, таких как хэш-таблица. Два объекта, которые относятся к одному типу и равны, должны возвращать один и тот же хэш-код, чтобы убедиться, что экземпляры следующих типов работают правильно:
Типы, которые реализуют System.Collections.Generic.IEqualityComparer<T>
Устранение нарушений
Чтобы устранить нарушение этого правила, предоставьте реализацию GetHashCode. Для пары объектов одного типа необходимо убедиться, что реализация возвращает то же значение, если реализация Equals возвращается true
для пары.
Когда лучше отключить предупреждения
Для этого правила отключать вывод предупреждений не следует.
Пример класса
Description
В следующем примере показан класс (ссылочный тип), нарушающий правило.
Код
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);
}
}
}
Пример структуры
Description
В следующем примере показана структура (тип значения), которая нарушает это правило.
Код
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
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по