Source generator for Equals and GetHashCode with attribute based control of equality implementation
$ dotnet add package Equatable.GeneratorSource generator for Equals and GetHashCode with attribute based control of equality implementation
Equals and GetHashCodeIEquatable<T>class, record and struct typesEqualityComparer per property via attributeAdd the nuget package to your projects.
dotnet add package Equatable.Generator
Prevent including Equatable.Generator as a dependency
<PackageReference Include="Equatable.Generator" PrivateAssets="all" />
This library requires:
LangVersion 8.0 or higherPlace [Equatable] attribute on a class, record or struct. The source generator will create a partial with overrides for Equals and GetHashCode for all public properties.
[Equatable] Marks the class to generate overrides for Equals and GetHashCodeThe default comparer used in the implementation of Equals and GetHashCode is EqualityComparer<T>.Default. Customize the comparer used with the following attributes.
[IgnoreEquality] Ignore property in Equals and GetHashCode implementations[StringEquality] Use specified StringComparer when comparing strings[SequenceEquality] Use Enumerable.SequenceEqual to determine whether enumerables are equal[DictionaryEquality] Use to determine if dictionaries are equal[HashSetEquality] Use ISet<T>.SetEquals to determine whether enumerables are equal[ReferenceEquality] Use Object.ReferenceEquals to determines whether instances are the same instance[EqualityComparer] Use the specified EqualityComparerExample of using the attributes to customize the source generation of Equals and GetHashCode
[Equatable]
public partial class UserImport
{
[StringEquality(StringComparison.OrdinalIgnoreCase)]
public string EmailAddress { get; set; } = null!;
public string? DisplayName { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
public DateTimeOffset? LastLogin { get; set; }
[IgnoreEquality]
public string FullName => $"{FirstName} {LastName}";
[HashSetEquality]
public HashSet<string>? Roles { get; set; }
[DictionaryEquality]
public Dictionary<string, int>? Permissions { get; set; }
[SequenceEquality]
public List<DateTimeOffset>? History { get; set; }
}
Works for record types too
[Equatable]
public partial record StatusRecord(
int Id,
[property: StringEquality(StringComparison.OrdinalIgnoreCase)] string Name,
string? Description,
int DisplayOrder,
bool IsActive,
[property: SequenceEquality] List<string> Versions
);