wtorek, 19 marca 2013

Z Func do IEqualityComparer

Brakuje mi jednej klasy w BCL, która mogła by stworzyć obiekt implementujący IEqualityComparer z wyrażenia lambda . Ten temat był już wałkowany, ale pomimo tego napiszę czego mi brakuje i jakie jest zastosowanie.

Mamy klasę:
public class Value
{
    public int IntValue { get; set; }
    public string StringValue { get; set; }
    public override string ToString()
    {
        return IntValue + "_" + StringValue;
    }
}

Tworzymy comperer (klasa porównująca dwa obiekty), w którym podajemy funkcję zwracającą informację po jakim będziemy porównywać obiekty. Ta funkcja będzie nam potrzebne do tworzenia hash kodu.
public class KeyEqualityComparer<T> : IEqualityComparer<T>
{
    public Func<T, object> _keyToCompar { get; private set; }

    public KeyEqualityComparer(Func<T, object> keyToCompar)
    {
        _keyToCompar = keyToCompar;
    }

    public bool Equals(T x, T y)
    {
        return _keyToCompar(x).Equals(_keyToCompar(y));
    }

    public int GetHashCode(T obj)
    {
        return _keyToCompar(obj).GetHashCode();
    }
}

Aby przedstawić KeyEqualityComparer wystarczy wywołać następujący kod:
var list = new List<Value>
{
    new Value {IntValue = 1, StringValue = "One "},
    new Value {IntValue = 1, StringValue = "Two"}
};

var distinctList1 = list.Distinct(new KeyEqualityComparer<Value>(x =>x.IntValue));

Dodatkowo możemy stworzyć extension method:
public static IEqualityComparer<T> ToEqualityComparer<T>(this  Func<T, object> func)
{
    KeyEqualityComparer<T> equalityComparer = new KeyEqualityComparer<T>(func);
    return equalityComparer;
}

I wtedy możemy operować za pomocą wyrażeniu lambda:
Func<Value, object> keyToCompare = x => x.IntValue;
var distinctList = list.Distinct(keyToCompare.ToEqualityComparer());


Brak komentarzy:

Prześlij komentarz