听起来 ILsizeof
指令可能是您需要的。该sizeof
指令由 C#sizeof
运算符在幕后使用,但 IL 版本由于某种原因限制较少。
ECMA CLI 规范(第III 部分,第 4.25 节)对sizeof
指令有以下描述:
返回类型的大小(以字节为单位)。typeTok
可以是泛型参数、引用类型或值类型。
对于引用类型,返回的大小是对应类型的引用值的大小,而不是引用值所引用的对象中存储的数据大小。
[基本原理:值类型的定义可以在 CIL 生成时间和加载执行时间之间发生变化。因此,在生成 CIL 时,类型的大小并不总是已知的。该sizeof
指令允许 CIL 代码在运行时确定大小,而无需调用框架类库。计算可以完全在运行时或在 CIL 到本机代码的编译时进行。sizeof
返回此类型数组中每个元素将占用的总大小——包括实现选择添加的任何填充。具体来说,数组元素以sizeof
字节为单位。结束理由]
您应该能够通过sizeof
一些简单的运行时代码生成来获取指令:
Console.WriteLine("Entry is " + TypeHelper.SizeOf(typeof(Entry)) + " bytes.");
// ...
public static class TypeHelper
{
public static int SizeOf<T>(T? obj) where T : struct
{
if (obj == null) throw new ArgumentNullException("obj");
return SizeOf(typeof(T?));
}
public static int SizeOf<T>(T obj)
{
if (obj == null) throw new ArgumentNullException("obj");
return SizeOf(obj.GetType());
}
public static int SizeOf(Type t)
{
if (t == null) throw new ArgumentNullException("t");
return _cache.GetOrAdd(t, t2 =>
{
var dm = new DynamicMethod("$", typeof(int), Type.EmptyTypes);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, t2);
il.Emit(OpCodes.Ret);
var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>));
return func();
});
}
private static readonly ConcurrentDictionary<Type, int>
_cache = new ConcurrentDictionary<Type, int>();
}