具有通用类型字段的结构的大小 [英] Size of struct with generic type fields
问题描述
我想估计包含泛型类型参数的结构数组的大小,在这种情况下为字典条目结构.为此,我需要结构的大小.
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屋!