RSCG – Valuify

RSCG – Valuify
 
 

name Valuify
nuget https://www.nuget.org/packages/Valuify/
link https://github.com/MooVC/valuify
author Paul Martins

Generating Equals from properties

 

This is how you can use Valuify .

The code that you start with is


<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="Valuify" Version="1.1.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

 
</Project>


The code that you will use is


// See https://aka.ms/new-console-template for more information
using GeneratorEqualsDemo;
var p1 = new Person()
{
    ID = 1,
    FirstName = "Andrei",
    LastName = "Ignat"
};
var p2= new Person()
{
    ID = 1,
    FirstName = "Andrei",
    LastName = "Ignat"
};
Console.WriteLine(p1==p2);




namespace GeneratorEqualsDemo;

[Valuify.Valuify]
partial class Person
{
    public int ID { get; set; }
    public string? FirstName { get; set; }
  
    public string? LastName { get; set; }
}


 

The code that is generated is

namespace Valuify
{
    using System;
    using System.Diagnostics.CodeAnalysis;

    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    internal sealed class ValuifyAttribute
        : Attribute
    {
    }
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
    {
        public static bool operator ==(Person left, Person right)
        {
            if (ReferenceEquals(left, right))
            {
                return true;
            }

            if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
            {
                return false;
            }

            return global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(left.ID, right.ID)
                && global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(left.FirstName, right.FirstName)
                && global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(left.LastName, right.LastName);
        }
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
    {
        public sealed override bool Equals(object other)
        {
            return Equals(other as Person);
        }
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
    {
        public sealed override int GetHashCode()
        {
            return global::Valuify.Internal.HashCode.Combine(ID, FirstName, LastName);
        }
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
    {
        public bool Equals(Person other)
        {
            return this == other;
        }
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
        : IEquatable<Person>
    {
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
    {
        public static bool operator !=(Person left, Person right)
        {
            return !(left == right);
        }
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace GeneratorEqualsDemo
{
    using System;
    using System.Collections.Generic;

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable disable
    #endif

    partial class Person
    {
        public sealed override string ToString()
        {
            return string.Format("Person { ID = {0}, FirstName = {1}, LastName = {2} }", ID, FirstName, LastName);
        }
    }

    #if NET5_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
    #nullable restore
    #endif
}
namespace Valuify.Internal
{
    using System;
    using System.Collections;

    internal static class HashCode
    {
        private const int HashSeed = 0x1505;
        private const int HashPrime = -1521134295;

        public static int Combine(params object[] values)
        {
            int hash = HashSeed;

            foreach (object value in values)
            {
                if (value is IEnumerable && !(value is string))
                {
                    IEnumerable enumerable = (IEnumerable)value;

                    foreach (object element in enumerable)
                    {
                        hash = PerformCombine(hash, element);
                    }
                }
                else
                {
                    hash = PerformCombine(hash, value);
                }
            }

            return hash;
        }

        private static int PerformCombine(int hash, object value)
        {
            int other = GetHashCode(value);

            unchecked
            {
                return (other * HashPrime) + hash;
            }
        }

        private static int GetHashCode(object value)
        {
            int code = 0;

            if (value != null)
            {
                code = value.GetHashCode();
            }

            return code;
        }
    }
}
namespace Valuify.Internal
{
    using System;
    using System.Collections;

    internal sealed class SequenceEqualityComparer
    {
        public static readonly SequenceEqualityComparer Default = new SequenceEqualityComparer();

        public bool Equals(IEnumerable left, IEnumerable right)
        {
            if (ReferenceEquals(left, right))
            {
                return true;
            }

            if (ReferenceEquals(left, null) || ReferenceEquals(null, right))
            {
                return false;
            }

            return Equals(left.GetEnumerator(), right.GetEnumerator());
        }

        public int GetHashCode(IEnumerable enumerable)
        {
            return HashCode.Combine(enumerable);
        }

        private static bool Equals(IEnumerator left, IEnumerator right)
        {
            while (left.MoveNext())
            {
                if (!right.MoveNext())
                {
                    return false;
                }

                if (!Equals(left.Current, right.Current))
                {
                    return false;
                }
            }

            return !right.MoveNext();
        }
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Valuify