Equatable is a C# library designed to simplify and standardize value-based equality in your classes and structs. By leveraging this utility, you can avoid repetitive boilerplate code typically associated with overriding Equals() and GetHashCode().
Equatable becomes especially powerful when working with:
- JSON (de)serialization: Quickly compare deserialized objects for changes or synchronization.
- Large collections of diverse data types: Simplify equality checks across many instance types.
- Immutable data structures: Perfect for scenarios where equality must depend purely on value.
When handling a large number of instances or managing complex data models (common in APIs, distributed systems, or UI diffing logic), Equatable helps keep your code clean, consistent, and reliable.
- 🔁 Value-based equality without boilerplate
- 🧩 Easy integration with any class or struct
- 📦 Works seamlessly with collections and serialization scenarios
- 🧼 Improves readability and maintainability
You can easily install Equatable from NuGet:
dotnet add package Equatable --version 1.0.11Or via the NuGet Package Manager in Visual Studio:
Install-Package EquatableThis repository demonstrates how to implement value-based equality in C# using an abstract base class called BaseEquatable.
Instead of manually overriding Equals, GetHashCode, and ToString in every model, you can inherit from BaseEquatable and define which properties participate in equality through the Props list.
class Person
{
public string? Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return $"{Name}, {Age}";
}
public override bool Equals(object? obj)
{
if (obj is Person other)
{
return Name == other.Name && Age == other.Age;
}
return false;
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}-
Verbose and repetitive.
-
Easy to forget updating one method when properties change.
-
Harder to scale across multiple classes.
Note: If your class has many properties, the implementation of
EqualsandGetHashCodecan become more cumbersome and prone to errors. Each additional property you add to the class requires manual updates to theEqualsandGetHashCodemethods, leading to bloated code.
class Person : BaseEquatable
{
public string? Name { get; set; }
public int Age { get; set; }
public override List<object?> Props => [Name, Age];
public override bool? Stringify => true;
}-
No need to override Equals, GetHashCode, or ToString manually.
-
Consistent and reliable structural equality.
-
Easier to maintain and extend.
-
Cleaner, DRY (Don't Repeat Yourself) code.
var p1 = new Person { Name = "Rustam", Age = 30 };
var p2 = new Person { Name = "Rustam", Age = 30 };
var p3 = new Person { Name = "Iskandar", Age = 30 };
Console.WriteLine(p1.Equals(p2)); // True
Console.WriteLine(p1.Equals(p3)); // False
Console.WriteLine(p1.GetHashCode() == p2.GetHashCode()); // True
Console.WriteLine(p1); // Rustam, 30 (if Stringify == true)If you find any issues, have suggestions, or ideas to improve this library, please feel free to open an issue in the Issues section. Contributions and ideas are welcome!
