.NET Compact Framework GetHashCode(对象)等效项
对于以下方法,.NETCompactFramework等效于什么?是否有任何P/Invoke调用可用 System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(对象).NET Compact Framework GetHashCode(对象)等效项,.net,compact-framework,.net,Compact Framework,对于以下方法,.NETCompactFramework等效于什么?是否有任何P/Invoke调用可用 System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(对象) 我正在进行一个开源项目,即.NETCompactFramework端口 此方法无法调用PInvoke。GetHashCode()实际上只是调用内部CLR方法(Object.InternalGetHashCode)。不可能将皮诺维奇引入这样一个函数 此方法实际上只是以非虚拟
我正在进行一个开源项目,即.NETCompactFramework端口 此方法无法调用PInvoke。GetHashCode()实际上只是调用内部CLR方法(Object.InternalGetHashCode)。不可能将皮诺维奇引入这样一个函数 此方法实际上只是以非虚拟方式调用Object.GetHashCode()。不幸的是,没有一种方法可以静态地做到这一点。C#不支持对给定对象非虚拟地调用方法(CLR认为这是不可验证的代码) 最好是通过反射调用Object.InternalGetHasheCode。不过,您必须检查并查看该方法是否在紧凑框架上实现。我的期望是,这将是,但我没有一个mscorlib的CF手边
RuntimeHelpers.GetHashCode的文档:我编写了一些代码,这些代码获得了一个身份哈希代码方法的委托,该方法可以在标准框架和压缩框架上工作,尽管它依赖于压缩框架中未记录的内部结构来完成。我忘记了实际的P/Invoke调用(它是从
mscoree.dll
)的顺序导出);这只是按名称从mscorlib
中获取内部P/Invoke原型
private static readonly Func<object, int> _IdentityHashCode;
static ClassName()
{
Assembly mscorlib = typeof(object).Assembly;
Type t;
MethodInfo mi;
// Try the official way first.
if ((t = mscorlib.GetType("System.Runtime.CompilerServices.RuntimeHelpers")) != null)
{
if ((mi = t.GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Static)) != null)
{
_IdentityHashCode = (Func<object, int>)Delegate.CreateDelegate(typeof(Func<object, int>), null, mi);
return;
}
}
// On Compact Framework we have to go in through the back door.
if ((t = mscorlib.GetType("System.PInvoke.EE")) != null)
{
if ((mi = t.GetMethod("Object_GetHashCode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) != null)
{
_IdentityHashCode = (Func<object, int>)Delegate.CreateDelegate(typeof(Func<object, int>), null, mi);
return;
}
}
_IdentityHashCode = LastDitchHashFunction;
}
private static int LastDitchHashFunction(object obj)
{
// A legal if very inefficient implementation ...
return 0;
}
private static readonly Func_IdentityHashCode;
静态类名()
{
Assembly mscorlib=类型(对象).Assembly;
t型;
MethodInfo-mi;
//先试试官方的方式。
if((t=mscorlib.GetType(“System.Runtime.CompilerServices.RuntimeHelpers”)!=null)
{
if((mi=t.GetMethod(“GetHashCode”,BindingFlags.Public | BindingFlags.Static))!=null)
{
_IdentityHashCode=(Func)Delegate.CreateDelegate(typeof(Func),null,mi);
返回;
}
}
//在紧凑型框架上,我们必须从后门进入。
if((t=mscorlib.GetType(“System.PInvoke.EE”)!=null)
{
if((mi=t.GetMethod(“Object_GetHashCode”,BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))!=null)
{
_IdentityHashCode=(Func)Delegate.CreateDelegate(typeof(Func),null,mi);
返回;
}
}
_IdentityHashCode=LastDitchHashFunction;
}
私有静态int-LastDitchHashFunction(对象obj)
{
//如果执行效率非常低,那么这是一个法律问题。。。
返回0;
}
我写这篇文章是为了解决这个问题,而不依赖于运行时.CompilerServices.RuntimeHelpers
(并非在每个运行时版本中都可用)、反射.Emit
(同样的问题)或PInvoking到未记录的方法(可能会发生变化)
它与Reflection.Emit
方法的作用相同,但直接写入相关CIL中:
ldarg.1
call instance int32 [mscorlib]System.Object::GetHashCode()
ret
正如CIL所说,这一点很简单——尽管99%的时候这是一个愚蠢的想法*,因为GetHashCode()
是虚拟的,因此99%的时间call
而不是callvirt
将是一个bug。因此,虽然C#使用非虚拟方法的callvirt
这一事实受到了一些人(嗯,我)的争论,但确实有道理,没有C#方式直接表达这一点
*项目名称背后的部分灵感;同一性的规律可以追溯到亚里士多德,但“A是A”与我认为99%的愚蠢哲学最为密切相关。使用<代码>调用< /> >而不是不可验证的>代码> Calvit ,在C语言中是不可能表达的。您可以在IL项目中或通过
Reflection.Emit()
编写可验证的CIL来执行此操作。当使用调用
而不是callvirt
时,您应该确保在调用之前包含一个显式的null检查,或者,您可能最终会遇到这样的情况:在托管代码中访问this
会产生NullReferenceException
@280Z28有时使用call
而不是callvirt
的原因恰恰是没有隐式的空检查。这不是那种情况,尽管在这种情况下,不检查null仍然可以很好地工作并获得所需的结果(它返回0
)。