我想基于以上回答和我的经验,看一些特定情况。
一个经验法则是,具有不同哈希码的两个实例应始终不相等,但如果它们具有相同的哈希码,则可能相等也可能不相等。GetHashCode()
用于快速区分实例,Equals()
用于验证相等性(无论对您来说意味着什么)。
此外,许多内置机制都会寻找 IEquatable<T>
的实现,因此最好声明一个重写了实际检查的 Equals(MyClass)
。
具有唯一 ID 的类
考虑一个具有唯一 ID 的类。然后 equals 操作将只检查 id。哈希也是如此,它完全依赖于id。
public class IdClass : IEquatable<IdClass>
{
public int ID { get; }
public string Name { get; }
#region IEquatable Members
public override bool Equals(object obj)
{
if (obj is IdClass other)
{
return Equals(other);
}
return false;
}
public virtual bool Equals(IdClass other)
{
if (other == null) return false;
return ID.Equals(other.ID);
}
public override int GetHashCode() => ID.GetHashCode();
#endregion
}
带属性的类
这种情况与上面类似,但比较取决于两个或更多属性,并且需要在哈希码中不对称地组合。这将在下一个场景中更加明显,但思想是如果一个属性具有哈希A
,另一个属性具有哈希B
,则结果应该与第一个属性具有哈希B
和另一个哈希A
的情况不同。
public class RefClass : IEquatable<RefClass>
{
public string Name { get; }
public int Age { get; }
#region IEquatable Members
public override bool Equals(object obj)
{
if (obj is RefClass other)
{
return Equals(other);
}
return false;
}
public virtual bool Equals(RefClass other)
{
if (other == null) { return false; }
return Name.Equals(other.Name)
&& Age.Equals(other.Age);
}
public override int GetHashCode()
{
unchecked
{
int hc = -1817952719;
hc = (-1521134295) * hc + Name.GetHashCode();
hc = (-1521134295) * hc + Age.GetHashCode();
return hc;
}
}
#endregion
}
基于值的类(结构体)
这与上面的情况几乎相同,只是基于值的类型(struct
声明)还需要重新定义==
和!=
以调用equals方法。
public struct ValClass : IEquatable<ValClass>
{
public int X { get; }
public int Y { get; }
#region IEquatable Members
public override bool Equals(object obj)
{
if (obj is ValClass other)
{
return Equals(other);
}
return false;
}
public static bool operator ==(ValClass target, ValClass other) { return target.Equals(other); }
public static bool operator !=(ValClass target, ValClass other) { return !(target == other); }
public bool Equals(ValClass other)
{
return X == other.X && Y == other.Y;
}
public override int GetHashCode()
{
unchecked
{
int hc = -1817952719;
hc = (-1521134295) * hc + X.GetHashCode();
hc = (-1521134295) * hc + Y.GetHashCode();
return hc;
}
}
#endregion
}
请注意,
struct
应该是不可变的,并且在声明中添加
readonly
关键字是一个好主意。
public readonly struct ValClass : IEquatable<ValClass>
{
}
return ("MyClass" + this.Id).GetHashCode();
(这只是您可能需要记住的内容)。 - Aidiakapi