C#: Getting size of a value-type variable at runtime?
I know languages such as C and C++ allow determining the size of data (structs, arrays, variables...) at runtime using sizeof() function. I tried that in C# and apparently it does not allow putting variables into the sizeof() function, but type defintions only (float, byte, Int32, uint, etc...), how am I supposed to do that?
Practically, I want this to happen:
int x;
Console.WriteLine(sizeof(x)); // Output: 4
AND NOT:
Console.WriteLine(sizeof(int)); // Output: 4
I'm sure there's some normal way to get the size of data at runtime in C#, yet google didn't give much help.. Here it is my last hope
Solution 1:
Following on from Cory's answer, if performance is important and you need to hit this code a lot then you could cache the size so that the dynamic method only needs to be built and executed once per type:
int x = 42;
Console.WriteLine(Utils.SizeOf(x)); // Output: 4
// ...
public static class Utils
{
public static int SizeOf<T>(T obj)
{
return SizeOfCache<T>.SizeOf;
}
private static class SizeOfCache<T>
{
public static readonly int SizeOf;
static SizeOfCache()
{
var dm = new DynamicMethod("func", typeof(int),
Type.EmptyTypes, typeof(Utils));
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, typeof(T));
il.Emit(OpCodes.Ret);
var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>));
SizeOf = func();
}
}
}
Solution 2:
To find the size of an arbitrary variable, x
, at runtime you can use Marshal.SizeOf:
System.Runtime.InteropServices.Marshal.SizeOf(x)
As mentioned by dtb, this function returns the size of the variable after marshalling, but in my experience that is usually the size you want, as in a pure managed environment the size of a variable is of little interest.
Solution 3:
The size of int
is always going to be 32 bits. Why would you need to get the size at runtime?
With that said, you could use Marshal.SizeOf()
, but that's really intended for unmanaged code only.
I stumbled upon some code that apparently will give you the size of a value type. It uses reflection and would be quite an expensive method call compared to the functionality you wanted to use (sizeof()
):
using System;
using System.Reflection;
using System.Reflection.Emit;
...
// GetManagedSize() returns the size of a structure whose type
// is 'type', as stored in managed memory. For any reference type
// this will simply return the size of a pointer (4 or 8).
public static int GetManagedSize(Type type)
{
// all this just to invoke one opcode with no arguments!
var method = new DynamicMethod("GetManagedSizeImpl", typeof(uint), new Type[0], typeof(TypeExtensions), false);
ILGenerator gen = method.GetILGenerator();
gen.Emit(OpCodes.Sizeof, type);
gen.Emit(OpCodes.Ret);
var func = (Func<uint>)method.CreateDelegate(typeof(Func<uint>));
return checked((int)func());
}