gpt4 book ai didi

c# - ILGenerator 在 int 上发出调用 GetHashCode

转载 作者:行者123 更新时间:2023-11-30 22:54:34 25 4
gpt4 key购买 nike

当我运行这段代码时:

var il = getHashCode.GetILGenerator();
il.Emit(OpCodes.Ldc_I4_S, 17); // put "17" on the stack
il.Emit(OpCodes.Call, typeof(Int32).GetMethod("GetHashCode", new Type[] { }));
il.Emit(OpCodes.Ret);

我收到 System.NullReferenceException:对象引用未设置到对象的实例。

当我装箱值时:

var il = getHashCode.GetILGenerator();
il.Emit(OpCodes.Ldc_I4_S, 17); // put "17" on the stack
il.Emit(OpCodes.Box, typeof(Int32));
il.Emit(OpCodes.Call, typeof(Int32).GetMethod("GetHashCode", new Type[] { }));
il.Emit(OpCodes.Ret);

返回值为-1875039000,但应该是17。

我怎样才能发出正确的调用?

最佳答案

GetHashCode() 是一个实例方法,因此您需要在“引用”上调用它。虽然您不需要装箱一个整数,但您需要压入堆栈的 this 参数不是整数值本身,而是指向整数值的指针。

因此,您需要一个局部变量,您可以在其中存储整数值,然后将指向该局部值的指针压入堆栈 (ldloca.s) 并调用实例方法:

static void Main(string[] args)
{
var method = new DynamicMethod("Get17HashCode", typeof(int), new Type[0], typeof(Program).Module);
var ilGenerator = method.GetILGenerator();
ilGenerator.DeclareLocal(typeof(int));
ilGenerator.Emit(OpCodes.Ldc_I4_S, 17);
ilGenerator.Emit(OpCodes.Stloc_0);
ilGenerator.Emit(OpCodes.Ldloca_S, 0);
ilGenerator.Emit(OpCodes.Call, typeof(int).GetMethod(nameof(int.GetHashCode)));
ilGenerator.Emit(OpCodes.Ret);

var delegateFunction = (Func<int>)method.CreateDelegate(typeof(Func<int>));

var result = delegateFunction();
Console.WriteLine($"Got {result}");
}

你得到 NullReferenceException 的原因可能是因为地址 17 仍然在 CLR 在地址 0 注册的虚拟内存页中为空引用注册了一个处理程序。较大的值应该导致 AccessViolationException: Attempted to read or write protected memory(假设堆栈上的短格式表示)。

关于c# - ILGenerator 在 int 上发出调用 GetHashCode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56120243/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com