C# 在实施IEqualityComparer时<;T>;。GetHashCode(T obj),我可以使用当前实例吗';s状态,还是必须使用obj?

C# 在实施IEqualityComparer时<;T>;。GetHashCode(T obj),我可以使用当前实例吗';s状态,还是必须使用obj?,c#,interface,polymorphism,C#,Interface,Polymorphism,为什么在我实现IEqualityComparer时,它有一个GetHashCode(T obj)参数?当然,它不是一个静态对象,所以为什么我不能使用当前实例的状态来生成哈希代码呢?this==obj 我很好奇,因为我正试图这样做: public abstract class BaseClass : IEqualityComparer<BaseClass> { public abstract int GetHashCode(BaseClass obj); } public c

为什么在我实现IEqualityComparer时,它有一个GetHashCode(T obj)参数?当然,它不是一个静态对象,所以为什么我不能使用当前实例的状态来生成哈希代码呢?
this==obj

我很好奇,因为我正试图这样做:

public abstract class BaseClass : IEqualityComparer<BaseClass>
{
    public abstract int GetHashCode(BaseClass obj);
}

public class DerivedClass : BaseClass
{
    public int MyData;

    public override int GetHashCode(BaseClass obj)
    {
        return MyData.GetHashCode();
        // Or do I have to do this:
        // return (DerivedClass)obj.MyData.GetHashCode();
    }
}
公共抽象类基类:IEqualityComparer
{
公共抽象int GetHashCode(基类obj);
}
公共类派生类:基类
{
公共数据;
公共覆盖int GetHashCode(基类obj)
{
返回MyData.GetHashCode();
//或者我必须这样做:
//return(DerivedClass)obj.MyData.GetHashCode();
}
}

我试图阻止执行强制转换,因为它被用在真正高性能的代码中。

如果您没有使用传入的
obj
参数中的信息,您的哈希代码将不会因不同的传入对象而变化,也不会有用。比较器不是要获取哈希代码或进行比较的对象的实例

事实上,您可以在
GetHashCode
中使用comaprer的本地字段,甚至可以将
MyData
作为哈希代码返回,如示例所示-它仍然满足
GetHashCode
要求“为同一对象返回相同的值数据”。但在您的示例中,比较器的所有哈希代码都是相同的,因此将其用于
字典将本质上把字典变成列表


这同样适用于
Equals
调用-实际上,您可以始终返回
true
,但它有多有用?

如果您不使用传入的
obj
参数中的信息,则哈希代码不会因不同的传入对象而变化,也不会有用。比较器不是要获取哈希代码或进行比较的对象的实例

事实上,您可以在
GetHashCode
中使用comaprer的本地字段,甚至可以将
MyData
作为哈希代码返回,如示例所示-它仍然满足
GetHashCode
要求“为同一对象返回相同的值数据”。但在您的示例中,比较器的所有哈希代码都是相同的,因此将其用于
字典将本质上把字典变成列表


这同样适用于
Equals
调用-实际上,您可以随时返回
true
,但它会有多大用处?

我认为这里的主要问题是您对它感到困惑

IEquatable
定义一种方法,用于确定当前实例(
this
)是否等于相同类型的实例。换句话说,它用于测试
objA.Equals(objB)
。在实现此接口时,建议您也重写
GetHashCode()
instance方法

IEqualityComparer
定义了用于测试给定类型的两个对象是否相等的方法,换句话说,它用于测试
comparer.Equals(objA,objB)
。因此有必要提供一个对象作为
GetHashCode
的参数(记住,它不同于它从
对象继承的
GetHashCode

你可以把
IEquatable
想象成你的对象的表达方式,“这就是我如何知道我是否与其他事物相等的方式”,而
IEqualityComparer
想象成你的对象的表达方式,“这就是我如何知道其他两个事物是否相等的方式”

有关如何在框架中使用这两个接口的一些好例子,请参见:

  • 它实现了
    IEquatable
  • 它实现了
    IEqualityComparer
您是否应该使用
IEqualityComparer
的当前状态来确定哈希代码?如果状态是可变的,那么使用哈希的任何地方(例如
哈希集
字典
)都将缓存哈希代码并用于高效查找。如果由于比较器的状态发生变化而导致哈希代码发生变化,那么将完全破坏存储哈希的数据结构的有用性。现在,如果状态是不可变的(即,它仅在创建比较器时设置,并且不能在比较器的整个生命周期内进行修改),那么可以,但我仍然建议您不要这样做,除非您有很好的理由


最后,您提到了性能。老实说,这听起来像。我建议不要太担心性能,直到您确定这一行代码导致了问题

我认为这里的主要问题是你把它弄糊涂了

IEquatable
定义一种方法,用于确定当前实例(
this
)是否等于相同类型的实例。换句话说,它用于测试
objA.Equals(objB)
。在实现此接口时,建议您也重写
GetHashCode()
instance方法

IEqualityComparer
定义了用于测试给定类型的两个对象是否相等的方法,换句话说,它用于测试
comparer.Equals(objA,objB)
。因此有必要提供一个对象作为
GetHashCode
的参数(记住,它不同于它从
对象继承的
GetHashCode

你可以把
IEquatable
想象成你的对象的表达方式,“这就是我如何知道我是否与其他事物相等的方式”,而
IEqualityComparer
想象成你的对象的表达方式,“这就是我如何知道其他两个事物是否相等的方式”

有关如何在框架中使用这两个接口的一些好例子,请参见:

  • 它实现了
    IEquatable
  • 它实现了
    IEqu