CA2218: GetHashCode beim Überschreiben von Equals überschreiben
TypeName |
OverrideGetHashCodeOnOverridingEquals |
CheckId |
CA2218 |
Kategorie |
Microsoft.Usage |
Unterbrechende Änderung |
Nicht unterbrechend |
Ursache
Ein öffentlicher Typ überschreibt Object.Equals, nicht jedoch Object.GetHashCode.
Regelbeschreibung
GetHashCode gibt einen Wert auf der Grundlage der aktuellen Instanz zurück, die sich für Hashalgorithmen und Datenstrukturen eignet, z. B. für eine Hashtabelle. Zwei Objekte, die den gleichen Typ aufweisen und gleich sind, müssen den gleichen Hashcode zurückgeben, damit sichergestellt ist, dass Instanzen der folgenden Typen einwandfrei arbeiten:
HashTable
Dictionary
SortDictionary
SortList
HybredDictionary
Typen, die IEqualityComparer implementieren
Behandeln von Verstößen
Um einen Verstoß gegen diese Regel zu beheben, stellen Sie eine Implementierung von GetHashCode bereit. Bei einem Paar von Objekten des gleichen Typs müssen Sie sicherstellen, dass die Implementierung den gleichen Wert zurückgibt, wenn die Implementierung von Equals für das Paar true zurückgibt.
Wann sollten Warnungen unterdrückt werden?
Unterdrücken Sie keine Warnung dieser Regel.
Klassenbeispiel
Beschreibungen
Im folgenden Beispiel wird eine Klasse (Referenztyp) veranschaulicht, die gegen diese Regel verstößt.
Code
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;
}
}
}
Kommentar
Im folgenden Beispiel wird der Verstoß korrigiert, indem GetHashCode überschrieben wird.
Code
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);
}
}
}
Strukturbeispiel
Beschreibungen
Im folgenden Beispiel wird eine Struktur (Werttyp) veranschaulicht, die gegen diese Regel verstößt.
Code
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);
}
}
}
Kommentar
Im folgenden Beispiel wird der Verstoß korrigiert, indem GetHashCode überschrieben wird.
Code
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);
}
}
}
Verwandte Regeln
CA1046: Gleichheitsoperator für Referenztypen nicht überladen
CA2225: Operatorüberladungen weisen benannte Alternativen auf
CA2226: Operatoren sollten symmetrische Überladungen aufweisen
CA2224: Equals beim Überladen von Gleichheitsoperatoren überschreiben
CA2231: Überladen Sie den Gleichheitsoperator beim Überschreiben von ValueType.Equals
Siehe auch
Referenz
Richtlinien für die Implementierung der Equals-Methode und des Gleichheitsoperators (==)
HashTable