RuntimeHelpers.GetHashCode(object)
方法允许根据对象的标识生成哈希码。 MSDN states:
RuntimeHelpers.GetHashCode方法总是调用 Object.GetHashCode方法非虚拟化,即使对象的类型具有 重写了Object.GetHashCode方法。
[MethodImpl(MethodImplOptions.InternalCall)]
[SecuritySafeCritical]
public static extern int GetHashCode(object o);
但是,在使用Reflector(.NET 4.0)检查Object.GetHashCode()
方法时,我们将看到以下代码:
public virtual int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this);
}
这让我相信MSDN文档是错误的,因为从Object.GetHashCode
内调用RuntimeHelpers.GetHashCode(object)
会导致堆栈溢出。
那么RuntimeHelpers.GetHashCode(object)
的实际行为是什么?它是如何工作的?它如何计算哈希?
答案 0 :(得分:23)
我认为MSDN文档试图描述行为,而不是实现。关键点:RuntimeHelpers
会返回默认实施,如果object.GetHashCode()
未重写,您将获得此实现。
例如,如果要构建引用相等查找,即使对于已覆盖Equals
和GetHashCode
的类型,这也非常有用。我使用RuntimeHelpers.GetHashCode()
和Object.ReferenceEquals
在我维护的序列化程序中执行此操作。
答案 1 :(得分:11)
关键是object.GetHashCode()
可以被覆盖 - 并且经常是,例如按string
。这意味着您无法找到object.GetHashCode()
的默认实现返回的“身份哈希码”。
如果您想要实现一个仅认为是对象标识的HashSet
)的平等比较器,这将非常有用。
例如:
public class IdentityComparer<T> : IEqualityComparer<T> where T : class
{
public bool Equals(T x, T y)
{
// Just for clarity...
return object.ReferenceEquals(x, y);
}
public int GetHashCode(T x)
{
// The nullity check may be unnecessary due to a similar check in
// RuntimeHelpers.GetHashCode, but it's not documented
return x == null ? 0 : RuntimeHelpers.GetHashCode(x);
}
}
然后:
string x = "hello";
string y = new StringBuilder("h").Append("ello").ToString();
Console.WriteLine(x == y); // True (overloaded ==)
Console.WriteLine(x.GetHashCode() == y.GetHashCode()); // True (overridden)
IdentityComparer<string> comparer = new IdentityComparer<string>();
Console.WriteLine(comparer.Equals(x, y)); // False - not identity
// Very probably false; not absolutely guaranteed (as ever, collisions
// are possible)
Console.WriteLine(comparer.GetHashCode(x) == comparer.GetHashCode(y));
编辑:只是澄清一下......
那么RuntimeHelpers.GetHashCode(对象)的实际行为是什么?它是如何工作的?
观察到的行为是RuntimeHelpers.GetHashCode(object)
返回的值与从Object.GetHashCode()
的非虚拟调用返回的值相同。 (您无法轻松地在C#中编写非虚拟调用。)
关于如何工作 - 这是一个实现细节:) IMO在哪些方面发生事情(什么叫什么)并不重要。重要的是记录的行为,这是正确的。哎呀,不同版本的mscorlib可以以不同的方式实现它 - 从用户的角度来看根本不重要。没有反编译,你不应该分辨出来。
({1}} Object.GetHashCode
对RuntimeHelpers.GetHashCode()
进行记录会使(IMO)更加困惑。
答案 2 :(得分:4)
奇怪的是,当我通过Reflector查看System.Object.GetHashCode时,我看到了
public virtual int GetHashCode()
{
return InternalGetHashCode(this);
}
和runtimehelper:
public static int GetHashCode(object o)
{
return object.InternalGetHashCode(o);
}
也许这是一个框架差异?我正在看2.0组件。
答案 3 :(得分:0)
从您自己的问题来看,RuntimeHelpers.GetHashCode(Object)
实际上是非覆盖Object.GetHashCode()
的实现。