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 关注
- 148 浏览
添加回答
举报