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?
Edit
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.
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
Dictionary`2+Entry[System.Int32,System.Object]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
It sounds like the IL
sizeof
instruction could be what you need. Thesizeof
instruction is used by the C#sizeof
operator behind-the-scenes, but the IL version has fewer restrictions for some reason.The ECMA CLI specification (partition III, section 4.25) has this description of the
sizeof
instruction:You should be able to get at the
sizeof
instruction with a bit of simple runtime codegen:You may also use
Marshal.ReadIntPtr(type.TypeHandle.Value, 4)
. It returns basic instance size of the managed object. See http://msdn.microsoft.com/en-us/magazine/cc163791.aspx for more information about runtime memory layout.(After I wrote this, I noticed that the approach is anticipated in the rationale LukeH quoted)
I'm fairly sure that pinning and throwing away a tiny array is cheaper than dynamic compilation. Plus a static field in a generic class is a great way to have type-safe per-type data... no need for a
ConcurrentDictionary
.The approximated size would sum of the
hash
( 4 bytes (32 bit architecture)) +next
(4 bytes (32 bit architecture)) +TKey
(if reference type 4 bytes for the pointer (32 bit architecture), if value type the size of that value type calculated in recursion)) +TValue
(the same asTKey
)or
simply using Marshal.SizeOf method.