GetHashCode beim Überschreiben von Equals überschreiben
Aktualisiert: November 2007
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
Behandlung 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
Beschreibung
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;
}
}
}
Kommentare
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
Beschreibung
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);
}
}
}
Kommentare
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
Gleichheitsoperator bei Referenztypen nicht überladen
Operatorüberladungen haben benannte Alternativen
Operatoren sollten symmetrische Überladungen haben
Equals beim Überladen des Gleichheitsoperators überschreiben
Überladen Sie den Gleichheitsoperator beim Überschreiben von ValueType.Equals
Siehe auch
Referenz
Richtlinien für die Implementierung der Equals-Methode und des Gleichheitsoperators (==)
HashTable