Wenn Sie den Distinct linq-Operator verwenden, wird standardmäßig die Equals-Methode verwendet. Sie können jedoch mit Ihrem eigenen IEqualityComparer<T>
Objekt angeben, wann zwei Objekte mit einer benutzerdefinierten Logikimplementierung GetHashCode
und Equals
-methode gleich sind. Erinnere dich daran:
GetHashCode
sollte keinen starken CPU-Vergleich verwenden (z. B. nur einige offensichtliche grundlegende Überprüfungen verwenden) und als erstes angeben, ob zwei Objekte sicher unterschiedlich sind (wenn unterschiedliche Hash-Codes zurückgegeben werden) oder möglicherweise gleich (gleicher Hash-Code). In diesem letzten Fall, wenn zwei Objekte denselben Hashcode haben, prüft das Framework mithilfe der Equals-Methode als endgültige Entscheidung über die Gleichheit bestimmter Objekte.
Nachdem Sie MyType
und eine MyTypeEqualityComparer
Klasse Code befolgt haben, stellen Sie nicht sicher, dass die Sequenz ihre Reihenfolge beibehält:
var cmp = new MyTypeEqualityComparer();
var lst = new List<MyType>();
// add some to lst
var q = lst.Distinct(cmp);
In der folgenden Sci-Bibliothek habe ich eine Erweiterungsmethode implementiert, um sicherzustellen, dass das Vector3D-Set die Reihenfolge beibehält, wenn eine bestimmte Erweiterungsmethode verwendet wird DistinctKeepOrder
:
relevanter Code folgt:
/// <summary>
/// support class for DistinctKeepOrder extension
/// </summary>
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);
}
}
Kurz gesagt, Vector3DWithOrder
kapseln Sie den Typ und eine Ordnungszahl, während der Vector3DWithOrderEqualityComparer
ursprüngliche Typvergleicher gekapselt wird.
und dies ist der Methodenhelfer, um die Aufrechterhaltung der Ordnung sicherzustellen
/// <summary>
/// retrieve distinct of given vector set ensuring to maintain given order
/// </summary>
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);
}
Hinweis : Weitere Untersuchungen könnten es ermöglichen, einen allgemeineren (Verwendung von Schnittstellen) und optimierten Weg zu finden (ohne das Objekt zu kapseln).