Skip to main content

Equatable.Generator by Eden Prairie

Nuget / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: Equatable.Generator

Source generator for Equals and GetHashCode

Author: Eden Prairie

NuGet: https://www.nuget.org/packages/Equatable.Generator/

You can find more details at https://github.com/loresoft/Equatable.Generator

Source : https://github.com/loresoft/Equatable.Generator

Original Readme

note

Equatable.Generator

Source generator for Equals and GetHashCode with attribute based control of equality implementation

Build Project

Coverage Status

Equatable.Generator

Features

  • Override Equals and GetHashCode
  • Implement IEquatable<T>
  • Support class, record and struct types
  • Support EqualityComparer per 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.

Usage

Add package

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" />

Requirements

This library requires:

  • Target framework .NET Standard 2.0 or greater
  • Project C# LangVersion 8.0 or higher

Equatable Attributes

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 for Equals and GetHashCode

    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 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 EqualityComparer

Example Usage

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

About

note

Generating Equals from properties

How to use

Example ( source csproj, source files )

This is the CSharp Project that references Equatable.Generator

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Equatable.Generator" Version="2.0.0" />
</ItemGroup>
</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated />
#nullable enable

namespace GeneratorEqualsDemo
{
partial class Person : global::System.IEquatable<global::GeneratorEqualsDemo.Person?>
{
/// <inheritdoc />
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Equatable.SourceGenerator", "2.0.0+10ad4b045a688eb10980afcd11ddb8e64505eda6")]
public bool Equals(global::GeneratorEqualsDemo.Person? other)
{
return !(other is null)
&& global::System.StringComparer.OrdinalIgnoreCase.Equals(FirstName, other.FirstName)
&& global::System.StringComparer.OrdinalIgnoreCase.Equals(LastName, other.LastName);

}

/// <inheritdoc />
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Equatable.SourceGenerator", "2.0.0+10ad4b045a688eb10980afcd11ddb8e64505eda6")]
public override bool Equals(object? obj)
{
return Equals(obj as global::GeneratorEqualsDemo.Person);
}

/// <inheritdoc />
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Equatable.SourceGenerator", "2.0.0+10ad4b045a688eb10980afcd11ddb8e64505eda6")]
public static bool operator ==(global::GeneratorEqualsDemo.Person? left, global::GeneratorEqualsDemo.Person? right)
{
return global::System.Collections.Generic.EqualityComparer<global::GeneratorEqualsDemo.Person?>.Default.Equals(left, right);
}

/// <inheritdoc />
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Equatable.SourceGenerator", "2.0.0+10ad4b045a688eb10980afcd11ddb8e64505eda6")]
public static bool operator !=(global::GeneratorEqualsDemo.Person? left, global::GeneratorEqualsDemo.Person? right)
{
return !(left == right);
}

/// <inheritdoc />
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Equatable.SourceGenerator", "2.0.0+10ad4b045a688eb10980afcd11ddb8e64505eda6")]
public override int GetHashCode(){
int hashCode = 1938039292;
hashCode = (hashCode * -1521134295) + global::System.StringComparer.OrdinalIgnoreCase.GetHashCode(FirstName!);
hashCode = (hashCode * -1521134295) + global::System.StringComparer.OrdinalIgnoreCase.GetHashCode(LastName!);
return hashCode;

}

}
}

Usefull

Download Example (.NET C# )

Share Equatable.Generator

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Equatable.Generator

In the same category (Equals) - 2 other generators

GeneratorEquals

Valuify