Getting the size of a field in bytes with C#

C#ReflectionByte

C# Problem Overview


I have a class, and I want to inspect its fields and report eventually how many bytes each field takes. I assume all fields are of type Int32, byte, etc.

How can I find out easily how many bytes does the field take?

I need something like:

Int32 a;
// int a_size = a.GetSizeInBytes;
// a_size should be 4

C# Solutions


Solution 1 - C#

You can't, basically. It will depend on padding, which may well be based on the CLR version you're using and the processor etc. It's easier to work out the total size of an object, assuming it has no references to other objects: create a big array, use GC.GetTotalMemory for a base point, fill the array with references to new instances of your type, and then call GetTotalMemory again. Take one value away from the other, and divide by the number of instances. You should probably create a single instance beforehand to make sure that no new JITted code contributes to the number. Yes, it's as hacky as it sounds - but I've used it to good effect before now.

Just yesterday I was thinking it would be a good idea to write a little helper class for this. Let me know if you'd be interested.

EDIT: There are two other suggestions, and I'd like to address them both.

Firstly, the sizeof operator: this only shows how much space the type takes up in the abstract, with no padding applied round it. (It includes padding within a structure, but not padding applied to a variable of that type within another type.)

Next, Marshal.SizeOf: this only shows the unmanaged size after marshalling, not the actual size in memory. As the documentation explicitly states:

> The size returned is the actually the > size of the unmanaged type. The > unmanaged and managed sizes of an > object can differ. For character > types, the size is affected by the > CharSet value applied to that class.

And again, padding can make a difference.

Just to clarify what I mean about padding being relevant, consider these two classes:

class FourBytes { byte a, b, c, d; }
class FiveBytes { byte a, b, c, d, e; }

On my x86 box, an instance of FourBytes takes 12 bytes (including overhead). An instance of FiveBytes takes 16 bytes. The only difference is the "e" variable - so does that take 4 bytes? Well, sort of... and sort of not. Fairly obviously, you could remove any single variable from FiveBytes to get the size back down to 12 bytes, but that doesn't mean that each of the variables takes up 4 bytes (think about removing all of them!). The cost of a single variable just isn't a concept which makes a lot of sense here.

Solution 2 - C#

Depending on the needs of the questionee, Marshal.SizeOf might or might not give you what you want. (Edited after Jon Skeet posted his answer).

using System;
using System.Runtime.InteropServices;

public class MyClass
{
	public static void Main()
	{
		Int32 a = 10;
		Console.WriteLine(Marshal.SizeOf(a));
		Console.ReadLine();
	}
}

Note that, as jkersch says, sizeof can be used, but unfortunately only with value types. If you need the size of a class, Marshal.SizeOf is the way to go.

Jon Skeet has laid out why neither sizeof nor Marshal.SizeOf is perfect. I guess the questionee needs to decide wether either is acceptable to his problem.

Solution 3 - C#

From Jon Skeets recipe in his answer I tried to make the helper class he was refering to. Suggestions for improvements are welcome.

public class MeasureSize<T>
{
    private readonly Func<T> _generator;
    private const int NumberOfInstances = 10000;
    private readonly T[] _memArray;

    public MeasureSize(Func<T> generator)
    {
        _generator = generator;
        _memArray = new T[NumberOfInstances];
    }
    
    public long GetByteSize()
    {
        //Make one to make sure it is jitted
        _generator();

        long oldSize = GC.GetTotalMemory(false);
        for(int i=0; i < NumberOfInstances; i++)
        {
            _memArray[i] = _generator();
        }
        long newSize = GC.GetTotalMemory(false);
        return (newSize - oldSize) / NumberOfInstances;
    }
}

Usage:

Should be created with a Func that generates new Instances of T. Make sure the same instance is not returned everytime. E.g. This would be fine:

    public long SizeOfSomeObject()
    {
        var measure = new MeasureSize<SomeObject>(() => new SomeObject());
        return measure.GetByteSize();
    }

Solution 4 - C#

It can be done indirectly, without considering the alignment. The number of bytes that reference type instance is equal service fields size + type fields size. Service fields(in 32x takes 4 bytes each, 64x 8 bytes):

  1. Sysblockindex
  2. Pointer to methods table
  3. +Optional(only for arrays) array size

So, for class without any fileds, his instance takes 8 bytes on 32x machine. If it is class with one field, reference on the same class instance, so, this class takes(64x):

Sysblockindex + pMthdTable + reference on class = 8 + 8 + 8 = 24 bytes

If it is value type, it does not have any instance fields, therefore in takes only his fileds size. For example if we have struct with one int field, then on 32x machine it takes only 4 bytes memory.

Solution 5 - C#

I had to boil this down all the way to IL level, but I finally got this functionality into C# with a very tiny library.

You can get it (BSD licensed) at bitbucket

Example code:

using Earlz.BareMetal;

...
Console.WriteLine(BareMetal.SizeOf<int>()); //returns 4 everywhere I've tested
Console.WriteLine(BareMetal.SizeOf<string>()); //returns 8 on 64-bit platforms and 4 on 32-bit
Console.WriteLine(BareMetal.SizeOf<Foo>()); //returns 16 in some places, 24 in others. Varies by platform and framework version

...

struct Foo
{
  int a, b;
  byte c;
  object foo;
}

Basically, what I did was write a quick class-method wrapper around the sizeof IL instruction. This instruction will get the raw amount of memory a reference to an object will use. For instance, if you had an array of T, then the sizeof instruction would tell you how many bytes apart each array element is.

This is extremely different from C#'s sizeof operator. For one, C# only allows pure value types because it's not really possible to get the size of anything else in a static manner. In contrast, the sizeof instruction works at a runtime level. So, however much memory a reference to a type would use during this particular instance would be returned.

You can see some more info and a bit more in-depth sample code at my blog

Solution 6 - C#

if you have the type, use the sizeof operator. it will return the type`s size in byte. e.g.

Console.WriteLine(sizeof(int));

will output:

4

Solution 7 - C#

You can use method overloading as a trick to determine the field size:

public static int FieldSize(int Field) { return sizeof(int); }
public static int FieldSize(bool Field) { return sizeof(bool); }
public static int FieldSize(SomeStructType Field) { return sizeof(SomeStructType); }

Solution 8 - C#

Simplest way is: int size = *((int*)type.TypeHandle.Value + 1)

I know this is implementation detail but GC relies on it and it needs to be as close to start of the methodtable for efficiency plus taking into consideration how GC code complex is nobody will dare to change it in future. In fact it works for every minor/major versions of .net framework+.net core. (Currently unable to test for 1.0)
If you want more reliable way, emit a struct in a dynamic assembly with [StructLayout(LayoutKind.Auto)] with exact same fields in same order, take its size with sizeof IL instruction. You may want to emit a static method within struct which simply returns this value. Then add 2IntPtr.Size for object header. This should give you exact value.
But if your class derives from another class, you need to find each size of base class seperatly and add them + 2
Inptr.Size again for header. You can do this by getting fields with BindingFlags.DeclaredOnly flag.

Solution 9 - C#

System.Runtime.CompilerServices.Unsafe

Use System.Runtime.CompilerServices.Unsafe.SizeOf<T>() where T: unmanaged

(when not running in .NET Core you need to install that NuGet package)

Documentation states:

> Returns the size of an object of the given type parameter.

It seems to use the sizeof IL-instruction just as Earlz solution does as well. (source)

The unmanaged constraint is new in C# 7.3

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionElazar LeibovichView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Lasse V. KarlsenView Answer on Stackoverflow
Solution 3 - C#Jesper NiedermannView Answer on Stackoverflow
Solution 4 - C#Sergey PopovView Answer on Stackoverflow
Solution 5 - C#EarlzView Answer on Stackoverflow
Solution 6 - C#Joachim KerschbaumerView Answer on Stackoverflow
Solution 7 - C#David ChenView Answer on Stackoverflow
Solution 8 - C#TakeMeAsAGuestView Answer on Stackoverflow
Solution 9 - C#Bruno ZellView Answer on Stackoverflow