4 回答

TA貢獻1874條經驗 獲得超12個贊
更新:我假設的第一個版本B
是從A
.
A.Equals
:
如果A
未密封,obj is A ...
則比較不同類型時可能會返回誤報。所以更正后的版本:
public override bool Equals(object obj){ return obj is A other && this.Prop == other.Prop && this.GetType() == other.GetType(); // not needed if A is sealed}
A.GetHashCode
:
base.GetHashCode
將為不同但相等的實例返回不同的哈希碼,這是錯誤的。改為從自身屬性派生哈希碼。如果Prop
表現得像一些 ID,則只需返回Prop.GetHashCode()
B.Equals
:
public override bool Equals(object obj) { return obj is B other && this.Prop.SequenceEqual(other.Prop) // will re-use A.Equals && this.Prop.GetType() == other.Prop.GetType() // not needed if different IReadOnlyList types are ok && this.GetType() == other.GetType(); // not needed if B is sealed }
B.GetHashCode
:
您可以聚合實例的哈希碼A
。這里我使用了一個簡單的 XOR,但如果相同的項目經常以不同的順序出現,你可以想出更奇特的東西。
return Prop.Aggregate(0, (h, i) => h ^ i.GetHashCode());

TA貢獻1862條經驗 獲得超7個贊
可以通過使用方法(來自命名空間)來實現Equals
列表,它確保一個列表中的每個項目都等于另一個列表中同一索引處的項目。SequenceEquals
System.Linq
然而,您可能會考慮改變的一件事是您對GetHashCode
.?如果兩個項目相等,此方法應返回相同的數字(盡管不能保證具有相同哈希碼的兩個項目相等)。使用base.GetHashCode()
不滿足這個要求,因為在這種情況下base
是;object
根據文檔,“引用類型的哈希碼是通過調用基類的 Object.GetHashCode 方法計算的,該方法根據對象的引用計算哈希碼”,因此對象僅在引用確切的對象時返回相同的 HashCode同一個對象。
應該HashCode
基于用于確定相等性的相同屬性,因此在這種情況下我們要使用Prop.GetHashCode()
for class?A
,并且我們想要聚合Prop
for class中所有項目的哈希碼B
。
這是重構類的一種方法:
public class A : IEquatable<A>
{
? ? public string Prop { get; }
? ? public A(string val)
? ? {
? ? ? ? Prop = val;
? ? }
? ? public bool Equals(A other)
? ? {
? ? ? ? if (other == null) return false;
? ? ? ? return Prop == other.Prop;
? ? }
? ? public override bool Equals(object obj)
? ? {
? ? ? ? return Equals(obj as A);
? ? }
? ? public override int GetHashCode()
? ? {
? ? ? ? return Prop.GetHashCode();
? ? }
}
public class B : IEquatable<B>
{
? ? public IReadOnlyList<A> Prop { get; }
? ? public B(IReadOnlyList<A> val)
? ? {
? ? ? ? Prop = val;
? ? }
? ? public bool Equals(B other)
? ? {
? ? ? ? if (other == null) return false;
? ? ? ? if (ReferenceEquals(this, other)) return true;
? ? ? ? if (Prop == null) return other.Prop == null;
? ? ? ? return other.Prop != null && Prop.SequenceEqual(other.Prop);
? ? }
? ? public override bool Equals(object obj)
? ? {
? ? ? ? return Equals(obj as B);
? ? }
? ? public override int GetHashCode()
? ? {
? ? ? ? return Prop?.Aggregate(17,
? ? ? ? ? ? (current, item) => current * 17 + item?.GetHashCode() ?? 0)
? ? ? ? ? ? ? ? ?? 0;
? ? }
}

TA貢獻1824條經驗 獲得超6個贊
Linq 包含一個有用的方法來比較集合:SequenceEqual
public override bool Equals(object obj)
{
? ? if (!(obj is B other))
? ? {
? ? ? ? return false;
? ? }
? ? if (this.Prop == null || other.Prop == null)
? ? {
? ? ? ? return false;
? ? }
? ? return this.Prop.SequenceEqual(other.Prop);
}
此外,IEquatable<T>在覆蓋 Equals 時實施。

TA貢獻1806條經驗 獲得超5個贊
這樣的事情怎么樣:
public override bool Equals(object obj)
{
if(!(obj is B))
{
return false;
}
var b = obj as B;
if(b.Prop.Count != this.Prop.Count)
{
return false;
}
for(var i =0; i < Prop.Count; i++)
{
if (!Prop.ElementAt(i).Equals(b.Prop.ElementAt(i)))
{
return false;
}
}
return true;
}
- 4 回答
- 0 關注
- 193 瀏覽
添加回答
舉報