【发布时间】:2020-11-25 10:34:14
【问题描述】:
我有界面旋转。由 QuarterRotation 类实现:
public interface Rotation {
bla...
}
还有一个实现:
public class QuarterRotation: Rotation, IEquatable<QuarterRotation>{
constructor etc.. bla...
public override GetHashCode() {
return [nice number to describe equality]
}
public override Equals(QuarterRotation other) {
return [equal when direction and rotation amount is equal]
}
}
不,我想把它放在这样的 HashSet 中,但相等性不成立:
var set = new HashSet<Rotation>() {new QuarterRotation(x,0)};
set.Contains(new QuarterRotation(x,0)); // should be true in my mind, but is false
这是由于我的自定义覆盖 GetHashCode 和 Equals 没有被调用,而是调用了 Object 版本。
这确实有效:
var set = new HashSet<QuarterRotation>() {new QuarterRotation(x,0)};
set.Contains(new QuarterRotation(x,0)); // is true
但这不是我的梦想。因为我不想承诺一种轮换。在 C# 中是否有可能我可以将这样的接口用于 HashSet?我觉得我理解的实际问题,但如果我错了,请纠正我。还可以进一步解释为什么从抽象的角度考虑不同的方式来解决此类集合是明智的,至少在 C# 中是这样的。
【问题讨论】:
-
你的班级为什么要实现
IEqualityComparer<T>?它不实现此接口的成员。你的意思是IEquatable<T>? -
你也应该覆盖
Equals(object) -
恐怕你的问题不清楚。
HashSet<T>将使用默认的相等比较器EqualityComparer<T>.Default。如果您的类型实现了IEquatable<T>,那么这将调用IEquatable<T>.Equals(T)方法,否则它将调用object.Equals(object)(这只是为了避免在T是值类型时装箱)。如果您实现自己的平等,您必须覆盖object.Equals(object)。除非T是值类型,否则实现IEquatable<T>并没有什么意义,但如果你这样做,object.Equals(object)通常会调用IEquatable<T>.Equals(T) -
@canton7 是的,谢谢,应该是平等的
-
@canton7 哦,不错,肯定忘了实现override Equals(object),还以为界面会遮住我……我就放上去,看看你是否让我梦想成真!跨度>
标签: c# interface hashset hashcode