Reputation: 182
Class A
{
int X {get;set;}
}
Class B : A
{
int Y {get;set;}
}
B myB;
Say for the sake of argument that an object of type A is 4 bytes and an object of type B is 4 bytes.
B is allocated/initialized/constructed and its contents are stored on the heap.
Is the size of B 8 bytes with the pointers of both X and Y in tandem, or is it two objects of 4 bytes each?
Is it still resulting in two objects like the following situation?
Class A {}
Class B
{
A myA;
}
B myB;
Can I presume, if these situations result in different data, that inheritance uses less heap allocation than construction due to the additional contained object having its data allocated -- and that the heap allocates this data outside its containing object?
Can I conclude that construction is much less memory efficient than inheritance?
Clarification: When initializing an object of subclass type, are the bytes of that object's parent class's properties stored alongside the bytes of the subclass's properties? Does B store a pointer to A or does it directly store the properties of A? If it stores a pointer to an instance of A, that would make it the same in memory as if it had a property of type A instead.
Addition: It was said that the data of B contains the data of A also in the first example. Are there two allocations or one allocation when allocating the memory of a subclassed object?
In the second example, you're allocating memory twice: once for the contained property object of type A and once again for the object class B, so I'm presuming that you have two distinct memory allocations and two distinct objects with a pointer to A inside B.
If a subclass only allocates memory once for the entire size of all its properties and all its inherited properties, and stores all that information inline, then wouldn't that make it a superior memory allocation approach than allocating multiple objects for one object?
Upvotes: 1
Views: 1557
Reputation: 6684
When initializing an object of subclass type, are the bytes of that object's parent class's properties stored alongside the bytes of the subclass's properties?
Yes, probably. C# itself doesn't specify much (if anything; I'm not super familiar with the spec) about the memory model. I'm fairly certain that's implementation-defined. However, an instance of Derived
containing a reference to an entirely independent instance of its Base
doesn't make sense for a couple reasons:
If Base
is abstract the memory model then not just allows for but actually requires the creation of an instance of an abstract class.
At the IL level managed pointers (the actual references) to Derived
can be dropped in anywhere a managed pointer to Base
is expected. Now, we can rule out the runtime performing some kind of conversion (e.g. referencing that Base
instance) because that would lose the RTTI. But we know that we can cast that Base
reference to a Derived
instance at runtime, so it must not be modifying the pointer.
This would introduce a wrinkle when trying to access and modify fields of Base
through an instance of Derived
, however. In that case the CLR would have to tack on field information to the instance v-table. Certainly not impossible, but at that point CLR implementors would just be going out of their way to make things more difficult for themselves. And as far as I can see there'd be no real benefit to doing things this way (unless you wanted to be able to change the inheritance hierarchy at runtime, which neither C# nor the CLR allow).
It would also incur a lot of rather pointless performance penalties by adding another layer of indirection that could have been avoided by just including the fields of Base
directly in an instance of Derived
.
Upvotes: 1
Reputation: 18265
Assuming you are running .NET on x86 architecture, an empty object has an overhead of 8 bytes (and a minimum size of 12 bytes). This means a new object()
would occupy 12 bytes in memory.
Considering the following class structure:
public class Parent // overhead 8 bytes
{
int a, b, c, d; // int 4 bytes * 4 = 16 bytes
}
public class Child : Parent // inherits everything
{ }
var parent = new Parent(); // 24 bytes
var child = new Child(); // 24 bytes [NOTE: this is a SINGLE object of type Child, not two objects Parent+Child]
They are objects of the same size because Child
does not declare any other field.
The following class structure instead:
public class Composable // overhead 8 bytes
{
int a, b, c, d; // int 4 bytes * 4 = 16 bytes
}
public class Composite // overhead 8 bytes
{
Composable c = new Composable(); // 4 bytes (reference on the heap)
}
var composable = new Composable(); // 24 bytes
var composite = new Composite(); // 36 bytes (24 + 12) [NOTE: this creates TWO different objects, with one referencing the other]
Will suffer of a slightly higher overhead for two reasons: the "empty object" overhead of a new object created and the reference allocated for the inner object on the stack.
Responding to your question: Yes, composition requires a slight more amount of memory then inheritance, but the numbers are really too small to be afraid of.
When initializing an object of subclass type, are the bytes of that object's parent class's properties stored alongside the bytes of the subclass's properties?
Yes they are, as clearly shown by the inheritance example: we have a single object containing all the fields of both its class and any inherited class.
It was said that the data of B contains the data of A also in the first example. Are there two allocations or one allocation when allocating the memory of a subclassed object?
One single allocation
In the second example, you're allocating memory twice: once for the contained property object of type A and once again for the object class B, so I'm presuming that you have two distinct memory allocations and two distinct objects with a pointer to A inside B.
You are almost correct, the second allocation happens only if you really create that object. In your example you are just declaring a field A myA
: this takes 4 bytes of memory (in x86) and no more. It will occupy more memory when you create that object (e.g. A myA = new A()
)
If a subclass only allocates memory once for the entire size of all its properties and all its inherited properties, and stores all that information inline, then wouldn't that make it a superior memory allocation approach than allocating multiple objects for one object?
Composition vs Inheritance have different characteristic, I do not believe it has any real-world impact but yes, inheritance occupies slightly less memory then Composition.
Reference: OF MEMORY AND STRINGS by C#... err... I mean Jon Skeet.
Upvotes: 4