add Equality Comparer class to base class for custom property classes in c#

571 views Asked by At

i'm using the ConcurrentDictionary were the key is made of a class with public properties.

after playing around with the code from (HashCode on decimal with IEqualityComparer in a ConcurrentDictionary) I wanted to find a solution, so I don't have to implement the class with interface IEqualityComparer for every property class I make.

I already made a base class that can check whether or not all public properties are set (or at least not the default value). So, I thought, let give it a try and add the IEqualityComparer class to the base class.

so far, I had this and it does work.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

    private void SomeMethod()
{
    ConcurrentDictionary<TwoUintsOneStringsKeyInfo,int> test = new  ConcurrentDictionary<TwoUintsOneStringsKeyInfo, int>(new    TwoUintsOneStringsKeyInfo.EqualityComparerElevenUintsKeyInfo());
    test.TryAdd(new TwoUintsOneStringsKeyInfo { IdOne = 1, IdTwo = 2, mySTring = "Hi" }, 1);
    test.TryAdd(new TwoUintsOneStringsKeyInfo { IdOne = 2, IdTwo = 3, mySTring = "hello" }, 2);
    test.TryAdd(new TwoUintsOneStringsKeyInfo { IdOne = 3, IdTwo = 4 }, 3);

    int result;
    test.TryGetValue(new TwoUintsOneStringsKeyInfo { IdOne = 2, IdTwo = 3, mySTring = "hello" }, out result);
}


    public class PropertyBaseClass
{
    public bool AllPublicProperiesAreSet()
    {
        //some logic (removed for now. Not important for the question)

    }

    public class EqualityComparerElevenUintsKeyInfo : IEqualityComparer<TwoUintsOneStringsKeyInfo>
    {
        public int GetHashCode(TwoUintsOneStringsKeyInfo obj)
        {
            int hash = 17;
            System.Reflection.PropertyInfo[] properties = obj.GetType().GetProperties().OrderBy(x=>x.Name).ToArray();
            int counter=0;
            foreach(System.Reflection.PropertyInfo p in properties)
            {
                counter++;
                var value = p.GetValue(obj);
                hash = hash * 23 + (value == null ? (Math.Pow(1.111, counter)).GetHashCode() : value.GetHashCode());
            }

            return hash;
        }

        public bool Equals(TwoUintsOneStringsKeyInfo x, TwoUintsOneStringsKeyInfo y)
        {
            return x.IdOne == y.IdOne &&
                    x.IdTwo == y.IdTwo;
        }
    }
}

public class TwoUintsOneStringsKeyInfo : PropertyBaseClass
{
    public uint IdOne { get; set; }
    public uint IdTwo { get; set; }
    public string mySTring { get; set; }
}

I made this example with just three properties. Normally there are more and also more different types and I just don't want to make a custom class to be used in the concurrentDictionary for every property class.

Thing is (of course), the way it is now, it will only work for property classes of type TwoUintsOneStringsKeyInfo, because I have to specify it when implementing the IEqualityComparer<>.

Is there any way I can implement the EqualityComparerElevenUintsKeyInfo class to the base class and making it flexible in a way that the EqualityComparerElevenUintsKeyInfo checks which class implements EqualityComparerElevenUintsKeyInfo and use that class as parameter for IEqualityComparer, GetHashCode and Equals (if it can be done to do what I want, I'll of course will change the Equals method as well.

Suggestions?

Kind regards,

Matthijs

0

There are 0 answers