Visual Studio Team System
Override GetHashCode on overriding Equals

TypeName

OverrideGetHashCodeOnOverridingEquals

CheckId

CA2218

Category

Microsoft.Usage

Breaking Change

Non Breaking

Cause

A public type overrides Object..::.Equals but does not override Object..::.GetHashCode.

Rule Description

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:

How to Fix Violations

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.

When to Suppress Warnings

Do not suppress a warning from this rule.

Class Example

Description

The following example shows a class (reference type) that violates this rule.

Code

C#
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;        
        }    
    }
}

Comments

The following example fixes the violation by overriding GetHashCode.

Code

C#
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);        
        }    
    }
}
Structure Example

Description

The following example shows a structure (value type) that violates this rule.

Code

C#
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);        
        }    
    }
}

Comments

The following example fixes the violation by overriding GetHashCode.

Code

C#
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);        
        }    
    }
}
Related Rules

Do not overload operator equals on reference types

Operator overloads have named alternates

Operators should have symmetrical overloads

Override equals on overloading operator equals

Overload operator equals on overriding ValueType.Equals

See Also

Reference

HashTable
Tags :


Community Content

David McClelland
"fixed" class example is for struct, but should be a class

The version of the "fixed" class example above is for a struct, but should be for a class.

Here is a replacement "fixed" class example:

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 int GetHashCode()
{
return _X ^ _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;
}
}
}

Tags :

Page view tracker