Introduction
In one of the previous article I have discussed about the equality in C#. In that article I have shown why it is important to override the Equal() method of the base object class for value types. and what is the correct way to provide the equality for the value types in C#.
Why override Equality for Value types
Let’s see the reason for changing the equality behaviour for the value type and in which scenarios it would be a best bet to override the equality.
There are possibly three reasons for overriding equality for value types. Please check the figure below.
- Use the “==” equality operator for the Value type – By default we are not able to use the equality operator for the value types. To make it work we have to overload it in our value type.
- Performance – This is one of the main reason to override the value type. As we know from my previous article, equality in value type uses reflection to measure equality.
- Change the Meaning of equality – By default the base class implementation of the Equals() method uses each and every fields value to calculate the equality. But suppose if we have some private variable of the value type which we are using for internal calculation. And we do not want to include this private variable in equality comparison. In cases like this we should provide our own equality implementation
How to provide Equality for Value types
- Implement the IEquatable
to have type safe method and - Override the Equals() method to prevent from reflection to find the fields and compare
- Implement operator overload for equality operator to provide uniform equality comparison
- Implement “!=” also as C# demands it
- Always implement GethashCode() method as it is good coding practice.
Please have a look at the below code. Here we can see how to implement equality for the value type.
public struct Person { public string Name { get; set; } public static bool operator ==(Person x, Person y) { return object.Equals(x, y); } public static bool operator !=(Person x, Person y) { return !object.Equals(x, y); } public override bool Equals(object obj) { if (obj == null) return false; if (ReferenceEquals(obj, this)) return true; if (obj.GetType() != this.GetType()) return false; Person per = (Person)obj; return this.Name == per.Name; } public override int GetHashCode() { return Name.GetHashCode(); } }
Conclusion:
I have discussed about the equality in value types. Why is it important to override the default equality behaviour of the value types. And how it can help us to achieve better performance while working with value types in C#.
Dmitry Bytchenko says
Typo: “public class Person” is not a value type, it’s reference one; should be “public struct Person”
Vikram Chaudhary says
Thanks a lot for correcting me. This is what happens when we don’t review the code 🙂
Dmitry Bytchenko says
Error: “obj as Person” doesn’t compile for value types since value type – struct – can’t be null.
Should be a cast “Person per = (Person) obj;”
Dmitry Bytchenko says
Yet another problem with `return Name.GetHashCode();` if Name is `null` the code will throw exception.