CA2218: Override GetHashCode on overriding Equals
TypeName |
OverrideGetHashCodeOnOverridingEquals |
CheckId |
CA2218 |
Category |
Microsoft.Usage |
Breaking Change |
Non Breaking |
A public type overrides Object.Equals but does not override Object.GetHashCode.
GetHashCode returns a value, based on the current instance, that is suited for hashing algorithms and data structures such as a hash table. Two objects that are the same type and are equal must return the same hash code to ensure that instances of the following types work correctly:
-
Dictionary
-
SortDictionary
-
SortList
-
HybredDictionary
-
Types that implement IEqualityComparer
To fix a violation of this rule, provide an implementation of GetHashCode. For a pair of objects of the same type, you must ensure that the implementation returns the same value if your implementation of Equals returns true for the pair.
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; } } }
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); } } }
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); } } }