Will this implementation of comparing two objects in C# work quickly?

316 views Asked by At

I created an implementation of comparing two objects.

The IEquatable interface does not suit me because I need a list of specific properties and values that do not match.

Will such an implementation work quickly? Or maybe there is some ready-made solution unknown to me?

Here is an example of an object being compared

public class Person
{
    public string Name { get; set; }

    public DateTime DoB { get; set; }
}

Here is an additional extension used to get the property name

public static class ExpressionExtensions
{
    public static string GetMemberName(this Expression expression)
    {
        switch (expression.NodeType)
        {
            case ExpressionType.MemberAccess:
                return ((MemberExpression)expression).Member.Name;
            case ExpressionType.Convert:
                return GetMemberName(((UnaryExpression)expression).Operand);
            default:
                throw new NotSupportedException($"Expression type {expression.NodeType} not supported!");
        }
    }
}

Here is the base class for comparison

public abstract class CompareBase<TEntity1, TEntity2>
    where TEntity1 : class
    where TEntity2 : class
{
    public CompareBase(TEntity1 entity1, TEntity2 entity2)
    {
        _entity1 = entity1;
        _entity2 = entity2;
        Compare();
    }

    protected TEntity1 _entity1 { get; set; }

    protected TEntity2 _entity2 { get; set; }

    protected abstract void Compare();

    protected void CompareFields(Expression<Func<TEntity1, object>> fieldExp1, Expression<Func<TEntity2, object>> fieldExp2)
    {
        var fieldVal1 = fieldExp1.Compile()(_entity1);

        var fieldVal2 = fieldExp2.Compile()(_entity2);

        if (!fieldVal1.Equals(fieldVal2))
        {
            Diff.Add($"Field {typeof(TEntity1).Name}.{fieldExp1.Body.GetMemberName()}={fieldVal1} != field {typeof(TEntity2).Name}.{fieldExp2.Body.GetMemberName()}={fieldVal2}");
        }
    }

    public List<string> Diff { get; set; } = new List<string>();
}

Here is the inherited class for comparison

public class PersonCompare : CompareBase<Person, Person>
{
    public PersonCompare(Person entity1, Person entity2) : base(entity1, entity2) { }

    protected override void Compare()
    {
        CompareFields(x => x.Name, x => x.Name);

        CompareFields(x => x.DoB, x => x.DoB);
    }
}

Here is a usage example

var boy = new Person
{
    Name = "Peter",
    DoB = new DateTime(2000, 7, 10)
};

var girl = new Person
{
    Name = "Sarah",
    DoB = new DateTime(2001, 1, 12)
};

var compare = new PersonCompare(boy, girl);

compare.Diff.ForEach(x => System.Console.WriteLine(x));
1

There are 1 answers