为什么2委托实例返回相同的哈希code?实例、code

2023-09-04 01:32:33 作者:落荒而逃不及迎刃而解

取以下内容:

 变种X =新的行动(()=> {Console.Write();});
  变种Y =新的行动(()=> {});
  VAR一个= x.GetHash code();
  变种B = y.GetHash code();
  Console.WriteLine(A == B);
  Console.WriteLine(x == y)的;
 

这将打印:

 真
假
 

为什么C型相同的散列$ C $?

这是有点令人惊讶,并会使用委托在词典作为慢如列表(又名 O(N)进行查找)。

更新:

问题是为什么。 IOW谁作出这样的(傻)的决定呢?

一文学会哈希法解题,助你事半功倍 leetcode哈希表面试高频题目总结

有一个更好的散列code实现的将是:

 返回方法^目标==空? 0:Target.GetHash code();
//其中,方法是IntPtr的
 

解决方案

简单!由于这里是实施 GetHash code (坐在基类代理):

 公众覆盖INT GetHash code()
{
    返回base.GetType()GetHash code()。
}
 

(坐在基类 MulticastDelegate 其中将调用上面):

 公共密封覆盖INT GetHash code()
{
    如果(this.IsUnmanagedFunctionPtr())
    {
        返回ValueType.GetHash codeOfPtr(base._methodPtr);
    }
    [对象] objArray = this._invocationList为对象[];
    如果(objArray == NULL)
    {
        返回base.GetHash code();
    }
    INT NUM = 0;
    的for(int i = 0;我≤((INT)this._invocationCount);我++)
    {
        NUM =(NUM * 0×21)+ objArray [I] .GetHash code();
    }
    返回NUM;
}
 

使用诸如反射器的工具,我们可以看到code和它似乎是默认的实现是奇怪的,因为我们看到上面。

该类型值,这里将成为动作。因此,上述结果是正确

更新

Take the following:

  var x =  new Action(() => { Console.Write("") ; });
  var y = new Action(() => { });
  var a = x.GetHashCode();
  var b = y.GetHashCode();
  Console.WriteLine(a == b);
  Console.WriteLine(x == y);

This will print:

True
False

Why is the hashcode the same?

It is kinda surprising, and will make using delegates in a Dictionary as slow as a List (aka O(n) for lookups).

Update:

The question is why. IOW who made such a (silly) decision?

A better hashcode implementation would have been:

return Method ^ Target == null ? 0 : Target.GetHashcode();
// where Method is IntPtr

解决方案

Easy! Since here is the implementation of the GetHashCode (sitting on the base class Delegate):

public override int GetHashCode()
{
    return base.GetType().GetHashCode();
}

(sitting on the base class MulticastDelegate which will call above):

public sealed override int GetHashCode()
{
    if (this.IsUnmanagedFunctionPtr())
    {
        return ValueType.GetHashCodeOfPtr(base._methodPtr);
    }
    object[] objArray = this._invocationList as object[];
    if (objArray == null)
    {
        return base.GetHashCode();
    }
    int num = 0;
    for (int i = 0; i < ((int) this._invocationCount); i++)
    {
        num = (num * 0x21) + objArray[i].GetHashCode();
    }
    return num;
}

Using tools such as Reflector, we can see the code and it seems like the default implementation is as strange as we see above.

The type value here will be Action. Hence the result above is correct.

UPDATE