Domyślnie, gdy używasz operatora Distinct linq, używa metody Equals, ale możesz użyć własnego IEqualityComparer<T>obiektu do określenia, kiedy dwa obiekty są równe za pomocą niestandardowej implementacji logiki GetHashCodei Equalsmetody. Zapamietaj to:
GetHashCodenie powinien używać ciężkich porównań procesorów (np. używać tylko niektórych oczywistych podstawowych testów) i jest używany jako pierwszy do stwierdzenia, czy dwa obiekty są na pewno różne (jeśli zwracany jest inny kod skrótu) lub potencjalnie ten sam (ten sam kod skrótu). W tym ostatnim przypadku, gdy dwa obiekty mają ten sam kod skrótu, framework wykona krok, aby sprawdzić za pomocą metody Equals jako ostateczną decyzję o równości danych obiektów.
Po tym, jak masz MyTypei MyTypeEqualityComparerklasy podążają za kodem, nie gwarantuje to, że sekwencja zachowa swoją kolejność:
var cmp = new MyTypeEqualityComparer();
var lst = new List<MyType>();
var q = lst.Distinct(cmp);
W bibliotece follow sci zaimplementowałem metodę rozszerzającą, aby zapewnić, że zestaw Vector3D zachowuje kolejność podczas korzystania z określonej metody rozszerzenia DistinctKeepOrder:
odpowiedni kod jest następujący:
public class Vector3DWithOrder
{
public int Order { get; private set; }
public Vector3D Vector { get; private set; }
public Vector3DWithOrder(Vector3D v, int order)
{
Vector = v;
Order = order;
}
}
public class Vector3DWithOrderEqualityComparer : IEqualityComparer<Vector3DWithOrder>
{
Vector3DEqualityComparer cmp;
public Vector3DWithOrderEqualityComparer(Vector3DEqualityComparer _cmp)
{
cmp = _cmp;
}
public bool Equals(Vector3DWithOrder x, Vector3DWithOrder y)
{
return cmp.Equals(x.Vector, y.Vector);
}
public int GetHashCode(Vector3DWithOrder obj)
{
return cmp.GetHashCode(obj.Vector);
}
}
W skrócie Vector3DWithOrderhermetyzuje typ i liczbę całkowitą zamówienia, podczas gdy Vector3DWithOrderEqualityComparerhermetyzuje funkcję porównującą oryginalny typ.
i to jest pomocnik metody, aby zapewnić utrzymanie porządku
public static IEnumerable<Vector3D> DistinctKeepOrder(this IEnumerable<Vector3D> vectors, Vector3DEqualityComparer cmp)
{
var ocmp = new Vector3DWithOrderEqualityComparer(cmp);
return vectors
.Select((w, i) => new Vector3DWithOrder(w, i))
.Distinct(ocmp)
.OrderBy(w => w.Order)
.Select(w => w.Vector);
}
Uwaga : dalsze badania mogą pozwolić na znalezienie bardziej ogólnego (zastosowania interfejsów) i zoptymalizowanego sposobu (bez hermetyzacji obiektu).