CA2218: Zastąp GetHashCode przy zastępowaniu Equals
TypeName |
OverrideGetHashCodeOnOverridingEquals |
CheckId |
CA2218 |
Kategoria |
Microsoft.Usage |
Zmiana kluczowa |
Niekluczowa |
Przyczyna
Typ publiczny zastępuje Object.Equals, lecz nie zastępuje Object.GetHashCode.
Opis reguły
GetHashCode zwraca wartość opartą na bieżącym wystąpieniu, które jest odpowiednie dla algorytmów wyznaczających wartości skrótu i struktur danych, takich jak tabela skrótów.Dwa obiekty, które są tego samego typu i są równe muszą zwrócić tę samą wartość skrótu, aby zapewnić prawidłowe działanie wystąpień poniższych typów:
Dictionary
SortDictionary
SortList
HybredDictionary
Typy implementujące IEqualityComparer
Jak naprawić naruszenia
Aby naprawić naruszenie tej reguły, dostarcz implementację GetHashCode.Dla pary obiektów tego samego typu, należy zapewnić, że implementacja zwróci tę samą wartość, jeśli implementacja użytkownika Equals zwraca true dla tej pary.
Kiedy pominąć ostrzeżenia
Nie należy pomijać ostrzeżenia dotyczącego tej reguły.
Przykład klasy
Opis
Poniższy przykład pokazuje klasę (typ odwołania) naruszający tę regułę.
Kod
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;
}
}
}
Komentarze
Poniższy przykład rozwiązuje naruszenie poprzez nadpisanie GetHashCode.
Kod
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);
}
}
}
Przykład struktury
Opis
Poniższy przykład pokazuje strukturę (typ wartości) naruszający tę regułę.
Kod
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);
}
}
}
Komentarze
Poniższy przykład rozwiązuje naruszenie poprzez nadpisanie GetHashCode.
Kod
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);
}
}
}
Powiązane reguły
CA1046: Nie przeciążaj operatora equals w typach referencyjnych
CA2225: Operator overloads ma nazwanych zastępców
CA2226: Operatory powinny być przeciążane symetrycznie
CA2224: Zastąp metodę equals przeciążając operator equals
CA2231: Przeciąż operator equals przy zastępowaniu ValueType.Equals
Zobacz też
Informacje
Inne zasoby
Guidelines for Implementing Equals and the Equality Operator (==)