[英]Distinct() not working as expected, and not calling Equals method, on a List of user defined objects
我已經創建了自己的 Tuple 定義,以便我可以對 Equals 方法有自己的定義,其中 (1, 3) 等於 (3, 1)。 代碼如下。
public struct Tuple : IEquatable<object>
{
public int Item1 { get; set; }
public int Item2 { get; set; }
public Tuple(int item1, int item2)
{
this.Item1 = item1;
this.Item2 = item2;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (Object.ReferenceEquals(this, obj))
return true;
Tuple other;
if (obj is Tuple)
{
other = (Tuple)obj;
}
else
{
return false;
}
if (this.Item1 == other.Item1 && this.Item2 == other.Item2
|| this.Item1 == other.Item2 && this.Item2 == other.Item1)
{
return true;
}
return false;
}
public override int GetHashCode()
{
int hash = 13;
hash = (hash * 7) + Item1.GetHashCode();
hash = (hash * 7) + Item2.GetHashCode();
return hash;
}
public static bool operator ==(Tuple left, Tuple right)
{
return left.Equals(right);
}
public static bool operator !=(Tuple left, Tuple right)
{
return !(left == right);
}
}
但是當我在元組列表上運行 distinct 時,它不使用我對 Equals 的定義。 例如,在頂點變量上,如下所示:
List<Tuple> vertices
我願意:
var distinctVertices = vertices.Distinct();
它確實檢查不同的值,但它沒有通過我的 Equals 定義,因此在我上面描述的情況下不起作用。 知道我可能做錯了什么嗎?
首先,您可能想要實現IEquatable<Tuple>
,而不是IEquatable<object>
- Tuple : IEquatable<Tuple>
。
其次,可變struct
上的相等是一個糟糕的想法; 我強烈建議您使用:
public readonly struct Tuple : IEquatable<Tuple>
{
public int Item1 { get; }
public int Item2 { get; }
public Tuple(int item1, int item2)
{
Item1 = item1;
Item2 = item2;
}
...
}
第三,您的Equals
和GetHashCode
必須一致。 如果順序對Equals
不重要,則對GetHashCode
不重要。 只考慮:
public override int GetHashCode() => Item1 ^ Item2;
或其他與訂單無關的東西。
最后,您的Equals
可能可以簡化:
public override bool Equals(object obj) => obj is Tuple other && Equals(other);
public bool Equals(Tuple other)
=> (Item1 == other.Item1 && Item2 == other.Item2)
|| (Item1 == other.Item2 && Item2 == other.Item1);
看看Distinct
文檔中的這個注釋:
該方法是通過使用延遲執行來實現的。 立即返回值是一個存儲執行操作所需的所有信息的對象。 在通過直接調用其 GetEnumerator 方法或在 Visual C# 中使用 foreach 或在 Visual Basic 中使用 For Each 來枚舉對象之前,不會執行此方法表示的查詢。
這意味着,在您枚舉結果之前,在過濾序列方面不會發生任何事情。
如果您對結果執行foreach
或添加ToList
,即:
var distinctVertices = vertices.Distinct().ToList();
或者
foreach(var vertice in distinctVertices)
{
// optionally do something here
}
然后你會看到你的Equals
方法被執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.