По умолчанию при использовании Distinct оператор linq использует метод Equals, но вы можете использовать свой собственный IEqualityComparer<T>
объект, чтобы указать, когда два объекта равны, с реализацией пользовательской логики GetHashCode
и Equals
методом. Помните, что:
GetHashCode
не следует использовать тяжелое сравнение процессоров (например, использовать только некоторые очевидные базовые проверки) и использовать его в качестве первого, чтобы указать, действительно ли два объекта отличаются (если возвращен другой хеш-код) или потенциально одинаковы (тот же хеш-код). В этом последнем случае, когда два объекта имеют один и тот же хэш-код, структура будет проверять, используя метод Equals в качестве окончательного решения о равенстве данных объектов.
После того, как вы есть , MyType
и через MyTypeEqualityComparer
классы следуют код не обеспечивает последовательность сохранять порядок:
var cmp = new MyTypeEqualityComparer();
var lst = new List<MyType>();
var q = lst.Distinct(cmp);
В следующей научной библиотеке я реализовал метод расширения, чтобы гарантировать, что набор Vector3D поддерживает порядок при использовании определенного метода расширения.DistinctKeepOrder
:
соответствующий код:
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);
}
}
Вкратце Vector3DWithOrder
инкапсулируйте тип и целое число порядка, аVector3DWithOrderEqualityComparer
инкапсулирует компаратор исходного типа.
и это помощник метода для обеспечения порядка
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);
}
Примечание : дальнейшие исследования могут позволить найти более общий (использование интерфейсов) и оптимизированный способ (без инкапсуляции объекта).