具有通用类型字段的结构的大小 [英] Size of struct with generic type fields

查看:39
本文介绍了具有通用类型字段的结构的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想估计包含泛型类型参数的结构数组的大小,在这种情况下为字典条目结构.为此,我需要结构的大小.

I want to estimate the size of an array of structs containing generic type parameters, in this case a dictionary entry struct. To do that I need the size of the struct.

struct Entry
{
   int hash;
   int next;
   TKey key;
   TValue value;
}

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

How can I get the size in bytes of this struct?

修改

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

It seems using Marshal.SizeOf is problematic. Passing the type of the struct will raise an exception saying that the argument can't be a generic type definition.

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

If I instead call the overload that takes an instance, e.g. Marshal.SizeOf(default(Entry)) it will work if both generic type arguments are value types. If the generic arguments are e.g. <int, object> then this exception is thrown

字典'2 + Entry [System.Int32,System.Object]'无法编组为不受管理的结构;无法计算出有意义的尺寸或偏移量.

Dictionary`2+Entry[System.Int32,System.Object]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

推荐答案

听起来像IL sizeof 幕后操作员,但由于某些原因,IL版本的限制较少.

It sounds like the IL sizeof instruction could be what you need. The sizeof instruction is used by the C# sizeof operator behind-the-scenes, but the IL version has fewer restrictions for some reason.

ECMA CLI规范(第III部分,第4.25节)具有以下描述: sizeof 指令:

The ECMA CLI specification (partition III, section 4.25) has this description of the sizeof instruction:

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

Returns the size, in bytes, of a type. typeTok can be a generic parameter, a reference type or a value type.

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

For a reference type, the size returned is the size of a reference value of the corresponding type, not the size of the data stored in objects referred to by a reference value.

[理性:值类型的定义可以在生成CIL的时间及其加载时间执行.因此,当CIL时并不总是知道类型的大小生成. sizeof 指令允许CIL代码确定运行时的大小,而无需调用Framework类图书馆.计算可以完全在运行时或在CIL到本地代码的编译时间. sizeof 返回总大小会被这种类型的数组中的每个元素占用–包括实现选择添加的任何填充.具体来说,数组元素相距 sizeof 个字节.基本原理]

[Rationale: The definition of a value type can change between the time the CIL is generated and the time that it is loaded for execution. Thus, the size of the type is not always known when the CIL is generated. The sizeof instruction allows CIL code to determine the size at runtime without the need to call into the Framework class library. The computation can occur entirely at runtime or at CIL-to-native-code compilation time. sizeof returns the total size that would be occupied by each element in an array of this type – including any padding the implementation chooses to add. Specifically, array elements lie sizeof bytes apart. end rationale]

您应该能够通过一些简单的运行时代码生成获得 sizeof 指令:

You should be able to get at the sizeof instruction with a bit of simple runtime 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>();
}

这篇关于具有通用类型字段的结构的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆