我有一組域物件,從基地,在那里我已經覆寫推導Equals,IEquatable<T>.Equals和平等的運營商。我已經成功使用了Contains,但現在我正在嘗試以Distinct不同的方式使用。下面是一個示例代碼:
var a = new Test { Id = 1 };
var a2 = new Test { Id = 1 };
var list = new List<Test> { a, a2 };
var distinct = list.Distinct().ToList(); // both objects, Equal implementations not called
var containsA = list.Contains(a); // true, Equal implementations called
var containsA2 = list.Contains(a); // true
var containsNewObjectWithSameId = list.Contains(new Test { Id = 1 }); // true
public class Test : IEquatable<Test>
{
public int Id { get; init; }
public bool Equals(Test other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
if (this.GetType() != other.GetType())
return false;
return this.Id == other.Id;
}
public override int GetHashCode() => base.GetHashCode this.Id;
}
Contains找到匹配項,但Distinct感覺非常具有包容性并同時保留了它們。來自 MS 檔案:
第一次搜索沒有指定任何相等比較器,這意味著 FindFirst 使用 EqualityComparer.Default 來確定框的相等性。這反過來使用 Box 類中 IEquatable.Equals 方法的實作。
我錯過了什么?
uj5u.com熱心網友回復:
感謝@JonSkeet 對評論的見解。
這種情況下的問題是我撰寫GetHashCode方法的方式。正如我最初認為的那樣,它與 LINQ 無關。
解釋
GetHashCode對于同等比較的物件,必須是相同的。在我的情況下 - 由于object.Equals僅檢查參考相等性的基本實作并且我正在比較兩個單獨的物件 - a和b,它們base.GetHashCode將導致不同的值,這反過來會使這兩個物件呈現不相等。
解決方案
在這種情況下,只需回傳 Id 值就足夠了,如 MS 檔案中所示:
計算范圍與 Int32 型別相同或更小的數值的哈希碼的最簡單方法之一是簡單地回傳該值。
所以像這樣改變上面的代碼示例:
public override int GetHashCode() => this.Id;
會解決這個問題。請記住,如果 的值Id不是唯一的,這將導致不良行為。在這種情況下,您需要檢查另一個屬性,并且必須GetHashCode從所有這些屬性進行組合。有關更多資訊,請參閱MS 檔案
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/374519.html
標籤:林克
上一篇:以一對多關系模型將記錄插入資料庫
