C# 用一个字段重写类中的Equals和GetHashCode

C# 用一个字段重写类中的Equals和GetHashCode,c#,overriding,equals,gethashcode,C#,Overriding,Equals,Gethashcode,我有一门课: public abstract class AbstractDictionaryObject { public virtual int LangId { get; set; } public override bool Equals(object obj) { if (obj == null || obj.GetType() != GetType()) {

我有一门课:

public abstract class AbstractDictionaryObject
    {
        public virtual int LangId { get; set; }

        public override bool Equals(object obj)
        {
            if (obj == null || obj.GetType() != GetType())
            {
                return false;
            }

            AbstractDictionaryObject other = (AbstractDictionaryObject)obj;
            if (other.LangId != LangId)
            {
                return false;
            }

            return true;
        }

        public override int GetHashCode()
        {
            int hashCode = 0;               
            hashCode = 19 * hashCode + LangId.GetHashCode();
            return hashCode;
        }
我有派生类:

public class Derived1:AbstractDictionaryObject
{...}

public class Derived2:AbstractDictionaryObject
{...}
AbstractDictionaryObject
中只有一个公共字段:
LangId

我认为这还不足以(正确地)重载方法。

如何识别对象

首先,您可以简化两种方法:

 public override bool Equals(object obj)
 {
     if (obj == null || obj.GetType() != GetType())
     {
         return false;
     }

     AbstractDictionaryObject other = (AbstractDictionaryObject)obj;
     return other.LangId == LangId;
 }

 public override int GetHashCode()
 {
     return LangId;
 }
但在这一点上,它应该是好的。如果两个派生类有其他字段,它们应该重写
GetHashCode
Equals
本身,首先调用
base.Equals
base.GetHashCode
,然后应用它们自己的逻辑

AbstractDictionaryObject
而言,具有相同
LangId的
Derived1
的两个实例将是等效的,两个
Derived2
的实例也将是等效的,但它们的类型不同,因此彼此不同

如果您想给他们不同的哈希代码,可以将
GetHashCode()
更改为:

 public override int GetHashCode()
 {
     int hash = 17;
     hash = hash * 31 + GetType().GetHashCode();
     hash = hash * 31 + LangId;
     return hash;
 }

但是,不同对象的哈希代码不必不同。。。它只是有助于提高性能。如果您知道将有不同类型的实例具有相同的
LangId
,那么您可能会想这样做,但如果不是这样,我就不麻烦了。

“两个具有相同LangId的Derived1实例将是等效的”-这对我的情况不利。我可以介绍GUID字段吗?因为我不想在派生类中重写。@user348173:如果您希望每个实例都与其他实例不相等,那么为什么要重写Equals和GetHashCode?现在还不清楚你想要实现什么。什么时候应该认为两个不同的对象相等?如果langId相等,而Derived1中存在的其他字段相等,则它们相等。例如,我有两个Derived1实例:Class1和Class2。字段LangId相等,但其他字段(例如-Name)不同。所以Class1和Class2不应该相等。但我不想覆盖Derived1中的Equals和GetHashCode。@user348173:但您应该覆盖Derived1中的Equals和GetHashCode。您可以潜在地使用反射来检查字段,但这将是缓慢且非常脆弱的-您可能希望引入一个字段,该字段不是Derived1中平等契约的一部分。基本上,基类无法预测类的哪些方面是其平等思想的一部分,因此需要在每个派生类中提供这种行为。为什么不在Derived1中重写GetHashCode/Equals?