Source generator for Equals and GetHashCode with attribute based control of equality implementation
- Override
EqualsandGetHashCode - Implement
IEquatable<T> - Support
class,recordandstructtypes - Support
EqualityComparerper property via attribute - Attribute based control of equality implementation.
- Attribute comparers supported: String, Sequence, Dictionary, HashSet, Reference, and Custom
- No runtime dependencies. Library is compile time dependence only.
Add 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:
- Target framework .NET Standard 2.0 or greater
- Project C#
LangVersion8.0 or higher
Place [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 forEqualsandGetHashCode
The 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 inEqualsandGetHashCodeimplementations[StringEquality]Use specifiedStringComparerwhen comparing strings[SequenceEquality]UseEnumerable.SequenceEqualto determine whether enumerables are equal[DictionaryEquality]Use to determine if dictionaries are equal[HashSetEquality]UseISet<T>.SetEqualsto determine whether enumerables are equal[ReferenceEquality]UseObject.ReferenceEqualsto determines whether instances are the same instance[EqualityComparer]Use the specifiedEqualityComparer
Example 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
);