警告:“…覆盖Object.Equals(对象o)但不覆盖Object.GetHashCode()”

我重写了我class级的Equals()来比较Guid类型的ID值。

然后Visual Studio警告:

…重写Object.Equals(object o)但不覆盖Object.GetHashCode()

所以我然后也像这样覆盖它的GetHashCode():

public partial class SomeClass { public override bool Equals(Object obj) { //Check for null and compare run-time types. if (obj == null || this.GetType() != obj.GetType()) return false; return this.Id == ((SomeClass)obj).Id; } public override int GetHashCode() { return this.Id.GetHashCode(); } } 

它似乎工作。 我做得对吗? 记住Id是Guid类型。 我的类是entity framework对象是否重要?

正如其他人所说,反平等的使用似乎很狡猾。 抛开这一点,让我们专注于GetHashCode。

您必须不违反GetHashCode的主要规则是, 如果两个对象相等,则它们必须具有相同的哈希码 。 或者,相同的说法是, 如果两个对象具有不同的哈希码,那么它们必须是不相等的。 你的实现看起来不错。

你可以自由地违反反过来。 也就是说,如果两个对象具有相同的哈希码,则允许它们相等或不相等,如您所见。

我假设“Id”是一个不可变的属性。 如果“Id”可以在对象的生命周期内更改,那么将对象放入哈希表时可能会出现问题。 考虑确保在计算相等性和哈希码时仅使用不可变属性。

您的实现看起来不错,但您提出问题的事实表明您可能无法掌握构建GetHashCode实现的所有细微因素。 一个好的开始是我关于这个主题的文章:

http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

它对我来说是正确的。 每当我做这样的事情时,我通常也会实现IEquatable以便在相同编译时类型的变量之间进行比较会更有效。

 public partial class SomeClass : IEquatable { public override bool Equals(Object obj) { return Equals(obj as SomeClass); } public bool Equals(SomeClass obj) { if (obj == null) return false; return Id == obj.Id; } public override int GetHashCode() { return Id.GetHashCode(); } } 

此结构还允许具有相同Id的更多派生对象进行比较,使其等于较少派生的对象。 如果这不是所需的行为,那么您还必须像在问题中那样比较类型。

 if (obj.GetType() != typeof(SomeClass)) return false; 

既然你没有处理一个密封的类,我建议不要像这样检查类的相等性this.GetType() != obj.GetType()SomeClass任何子类也应该能够参与Equals ,所以你可能想要使用它:

 if (obj as SomeClass == null) return false; 

传统上, Equals以这样一种方式实现,即如果两个对象在各方面都完全相同,那么它们将只是“等于”。 例如,如果您有两个对象代表数据库中的同一个对象,但是其中一个对象具有与另一个不同的Name属性,则对象不会被视为“Equal”,并且如果可能,应避免生成相同的“Hashcode” 。

最好是在“不平等”方面犯错,而不是冒险调用两个不相等的对象。 这就是对象的默认实现使用对象本身的内存位置的原因:除非它们是完全相同的对象,否则不会将两个对象视为“相等”。 所以我要说除非你想以这样的方式编写GetHashCodeEquals ,以便检查所有属性的相等性,否则最好不要覆盖任何一种方法。

如果您有一个数据结构(如HashSet ),您特别希望根据ID值确定相等性,则可以为该数据结构提供特定的IEqualityComparer实现。

你得到了第一个问题的优秀答案:

我做得对吗?

我会回答你的第二个问题

我的类是entity framework对象是否重要?

是的,这很重要。 entity framework在内部使用了很多HashSet 。 例如,动态代理使用HashSet表示集合导航属性,而EntityObject使用EntityCollection ,而EntityCollection又在内部使用HashSet