I received an answer in my question that talks about an overhead that the object has. Every object has this overhead ?
Does an object with no data also have this overhead ?
Is there an object of size 0?
I received an answer in my question that talks about an overhead that the object has. Every object has this overhead ?
Does an object with no data also have this overhead ?
Is there an object of size 0?
overhead only occurs at types by reference. In types per value it does not occur ever, it's just the cost of the same object. At least not the overhead of the header.
Every object is subject to alignment ( class organization ). So each allocation must be multiple of a word . At 64 bits it should always be every 16 bytes. So if the object has 25 bytes, in fact it will have 32 bytes.
If it's a reference type, it will always have a two-word header.
One is the type indicator of the object. It is important for the garbage collector, to know about the polymorphism, cast , reflection, etc.
The other word is called syncblock that is used to indicate where a monitoring object is in shared objects between threads .
As it is actually not so common its use like this, it can be used for other things. One of these things is to cache the hash code .
It is also used by the GC to make its control during the mark phase of what is still alive or not.
COM Objects need a reference to external and this space is used for this.
It may still contain the AppDomain ID in some cases.
But there's a catch. No object is less than 12 bytes in 32 bits, or 24 bytes in 64 bits. The object must have at least one "object state" word, even if it is empty. But if you have an object with a word, that cost is not added, it continues with 12 or 24 bytes in size.
Then not only does an object by reference have this overhead , but it has an overhead if it is empty or lower than a word.
Types by reference can not have size 0 as explained above. Types by value occupy at least 1 byte. This can be verified with:
using System;
class Program {
static void Main() {
var memoriaAnterior = GC.GetTotalMemory(true);
Console.WriteLine(memoriaAnterior);
var array = new None[1000000];
var memoriaAtual = GC.GetTotalMemory(true);
Console.WriteLine(memoriaAtual);
Console.WriteLine($"Diferença: { memoriaAtual - memoriaAnterior }");
Console.WriteLine(array.Length);
}
}
struct None {}
See running at Coding Ground . Also put it on GitHub for future reference .
To understand a little more: How does "free ()" know how much memory to free?
Note that this all depends on implementation. There are several implementations of CLR. We can see a different way .