具有泛型类型字段的struct的大小

And*_*ren 4 .net c# struct

我想估计包含泛型类型参数的结构数组的大小,在本例中是一个字典条目结构.要做到这一点,我需要结构的大小.

struct Entry
{
   int hash;
   int next;
   TKey key;
   TValue value;
}
Run Code Online (Sandbox Code Playgroud)

如何获得此结构的字节大小?

编辑

似乎使用Marshal.SizeOf是有问题的.传递结构的类型将引发一个异常,说该参数不能是泛型类型定义.

如果我改为调用带有实例的重载,例如,Marshal.SizeOf(default(Entry))如果两个泛型类型参数都是值类型,它将起作用.如果泛型参数是例如,<int, object>则抛出此异常

无法将字典`2 + Entry [System.Int32,System.Object]'封送为非托管结构; 不能计算有意义的大小或偏移量.

Luk*_*keH 9

听起来IL sizeof指令可能就是您所需要的.该sizeof指令由sizeof幕后的C#操作员使用,但由于某种原因,IL版本的限制较少.

ECMA CLI规范(分区III,节4.25)具有的描述sizeof指令:

返回类型的大小(以字节为单位).typeTok可以是通用参数,引用类型或值类型.

对于引用类型,返回的大小是相应类型的引用值的大小,而不是存储在引用值引用的对象中的数据的大小.

[基本原理:值类型的定义可以在生成CIL的时间和加载执行的时间之间变化.因此,在生成CIL时,并不总是知道该类型的大小.该sizeof指令允许CIL代码在运行时确定大小,而无需调用Framework类库.计算可以完全在运行时或在CIL到本机代码编译时进行.sizeof返回此类型数组中每个元素占用的总大小 - 包括实现选择添加的任何填充.具体而言,数组元素sizeof相隔字节.最终理由 ]

您应该能够sizeof使用一些简单的运行时codegen 来获取指令:

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>();
}
Run Code Online (Sandbox Code Playgroud)