consider the following code:
class Base
{
}
class Derived : Base
{
// some code
}
and from main if we do
Derived d = new Derived();
I have two questions:
Q1-We know when we do new Derived();CLR allocate a Derived object in the heap. But since Derived derives from Base, Derived implicit constructor also calls Base's implicit constructor, does it mean that there is also a Base object allocated in the heap?
Q2-(if the answer to Q1 is true) In GC's context, we refer to all reference type variables as roots. So for example, variable d is a root, and this root points to Derived object only. Here is a problem, there is no root variable to Base object, in theory Base object is always marked as unreachable by Garbage Collector and then get swept. which is obviously not correct, so does it mean that an implicit root variable will be assigned to Base object to keep it reachable?
You've misunderstood the nature of inheritance. There is just one object created here, an object of type Derived. The inheritance means that Derived gains some properties inherited from Base, but that does not mean another object of type Base is created. So to Q1, the answer is no. Therefore there is no need to answer Q2. The GC has one memory allocation to track, that for Derived.
When you create a new instance of a derived object (e.g. Derived d = new Derived();), a single object is allocated, not separate objects for the derived class and its base class.
Imagine they were both structs and you had to compose the derived object manually. You might end up with something like;
public struct Base {
...
}
public struct Derived {
public Base base;
...
}
The memory required for Base is contained within the memory footprint of Derived.
Related
Hope I'm not asking something that has been already answered in here.
If my class B inherits from class A, does new B() create two instances in heap where B instance contains pointer to A instance, or there will be created only one instance of B including A members?
From Microsoft Inheritance article :
This is how an object is represented in memory, given the Class Publication directly inherits the class Object.
So a inherited class is an object that contains all information about itself but also about its base class.
It will create one instance of B, and that B is also an A.
it will create B instance that (because of inheritance) already include A members, if i understood your question well
It creates one instance and you can access all the members of both A and B on that instance. As stated A is of type B as well. I imagine that in the low level code there probably exists a pointer to A.
I'm confused about how object allocation is done in the case of inheritance
consider the following code.
class Base
{
}
class Derived : Base
{
// some code
}
and from main if we do
Derived d = new Derived();
and
Base b = new Derived();
what is the memory allocation of both cases in the heap.
Is the derived object in inside base object or they both are beside each other
Memory allocation for both objects will look exactly the same. Both objects are of the same type Derived.
Of course, each object will be allocated in its own space on the heap.
What counts when creating objects is the class (type) used to construct the object, not the type of reference where object will be stored.
Each object exists as complete entity, but you can look at it as summary of all parts from all the classes it inherits from. In a way Derived object instance contains Base object instance inside. Not the other way around.
In both cases you instanciate objects of the concrete Derived class, so the memory footprint would be the same for both - you refer to them using references of the Base and the Derived class, but you instantiate the Derived class in both cases.
But as to providing a general answer to your question - yes, in memory instances of derived classes contain all the members of their base classes.
For the following classes:
public class Parent {
//Parent members
}
public class ChildA : Parent {
//ChildA members
}
public class ChildB : Parent {
//ChildB members
}
If I upcast ChildA or ChildB instance to a Parent instance, then I can't accesses their members, but their members are still there, because if I downcast and try to access their members again I will find that they still have their data.
I think this means that the Parent Instance keep allocating memory for the Child classes.
So does this mean when I instantiate a Parent Class that its allocating memory for the child classes members, or is that just happening when I cast?
And is it possible for a parent to allocate memory for more than one child if we go backward and forward with casting?
In the case you describe above, casting does not affect the memory that is allocated when casting from base to sub class and vice versa.
If you instantiate a Parent you will have a Parent object in memory. If you cast that to either of the child classes it will fail with an InvalidCastException.
If you instantiate either child you will have a child object in memory. You can cast this to the Parent and then back again. The memory allocation does not change in either case.
Additionally, if you instantiate a ChildA, cast to Parent and then attempt to cast to ChildB, you will get an InvalidCastException
"Normal" Upcasting and Downcasting of Reference Types
For reference types, casting variables doesn't change the type of the object already allocated on the heap, it just affects the type of the variable which references the object.
So no, there isn't any additional heap overhead with casting reference types (i.e. object instances from classes) provided that there are no custom conversion operators involved (See below, tolanj's comment).
Consider the following class hierarchy:
public class Fruit
{
public Color Colour {get; set;}
public bool Edible {get; set;}
}
public class Apple : Fruit
{
public Apple { Color = Green; Edible = true; KeepsDoctorAtBay = true;}
public bool KeepsDoctorAtBay{get; set;}
}
Which, when used with both upcasting and downcasting:
There is only ever one allocation on the heap, which is the initial var foo = new Apple().
After the various variable assignments, all three variables, foo, bar and baz point to the same object (an Apple instance on the heap).
Upcasting (Fruit bar = foo) will simply restrict the variable's available access to only Fruit methods and properties, and if the (Apple)bar downcast is successful all methods, properties and events of the downcast type will be available to the variable. If the downcast fails, an InvalidCastException will be thrown, as the type system will check the type of the heap object's compatability with the variable's type at run time.
Conversion Operators
As per tolanj's comment, all bets about the heap are off if an explicit conversion operator replaces the default casting of reference types.
For instance, if we add an unrelated class:
public class WaxApple // Not inherited from Fruit or Apple
{
public static explicit operator Apple(WaxApple wax)
{
return new Apple
{
Edible = false,
Colour = Color.Green,
KeepsDoctorAtBay = false
};
}
}
As you can imagine, WaxApple's explicit operator Apple can do whatever it likes, including allocate new objects on the heap.
var wax = new WaxApple();
var fakeApple = (Apple)wax;
// Explicit cast operator called, new heap allocation as per the conversion code.
A (down-)cast is nothing but a view onto an instance of a class by the "eyes of the parent class". Thus you´re neither losing nor adding any information nor memory by casting, you simply reference the same memory allready allocated for the original instance. This is the reason why you can still access (e.g. by reflection) the members of ChildA in the variable of type Parent. The information still exists, it is simply not visible.
So instead of having two memory-allocations you have two memory-references.
However be aware that this does not apply if you provide your own cast, e.g. from ChildA to ChildB. Doing so will typically look more or less similar to this:
public static explicit operator ChildA(ChildB b)
{
var a = new ChildA((Parent)b);
/* set further properties defined in ChildA but not in ChildB*/
}
Here you have two completely different instances, one of type ChildA and one of type ChildB which both consume their own memory.
I think this means that the Parent Instance keep allocating memory for the Child classes .
No, because Parent class does not know about it's children.
var a = new ClassA();
.NET allocates memory for all members of ClassA.
var b = (Parent)a;
.NET does not do anything with memory. a and b point to the same memory block (allocated for ClassA).
I need to clarify a thing that how an object type variables accept class type instance an given in the below code snippet,
class MyClass
{
}
static void Main()
{
object obj = new MyClass();
}
Since the MyClass is not a type of object but still the instance of MyClass is accepted in the obj(object) variable.
Actually, your class is an object.
In C# all classes derives from object.
Referring to a class as it's base type is one way of Polymorphism.
It might be better understood using an analogy:
Your class is an object, like a Dog is an animal.
Also, If you try the following:
object obj = new MyClass();
bool isMyType = obj == typeof(MyClass); //<--this will be true.
Take a look at this SO thread for more information how Polymorphism can be useful.
The concept that you do not understand is polymorphism which basically say that you can define an is relation between your classes. For a simple logic every dog is an animal so you can have class Dog that inherits from Animal. This implies that you can assign to variable of type Animal an instance of a Dog but not the other way around - not every animal is a dog. Another thing is that every thing derives form object this is language concept that you simply can take for granted.
Evrything in c# is derived from Object...
even your class.
.Net follows OOPs (Object Oriented Programming Language) and here every class can act as a object. Every class inherits Object class and hence every class can act as an object. In your example, .Net creates a default constructor to create instance of the class. You can definitely write your own constructor there.
Hope it helps.
Everything in C# is derived from Object.
Even Value Types like struct(int,float,..) are all derived from Object type.
When you define your own class,it implicitly derives from the Object type.
It is mentioned in the docs
All classes, structures, enumerations, and delegates inherit from
Object class
MSDN:
Supports all classes in the .NET Framework class hierarchy and provides low-level
services to derived classes. This is the ultimate base class of all classes
in the .NET Framework; it is the root of the type hierarchy.
Inheritance Hierarchy:
All classes, structures, enumerations, and delegates.
This means when you use int.Parse() to cast some value to int, there is a class behind int type which makes it able to have methods and do such stuffs. Object has been rooted pretty much everywhere in .Net.
I have a child and a parent class, as such:
class B : A{
public B : base(){
// stuff
}
}
class A{
public A(){
// how can I gain access here to the class that called me,
// ie the instance of class B that's being instantiated.
}
}
As above, my question is whether I can see who called the parent constructor within the constructor of the parent class.
One way to do this would be to have a separate function in A to which you pass this from within B. Is there anything simpler, ie can I do this during object initialization, or is that too early in the object construction process ? Does the whole object B need to be "ready" before I can access it from within A ?
Thanks!
Within A, it's easy - you just use this and cast it to B if you're confident that it really is a B rather than any other derived class. The object will already an instance of B.
However, it's generally a bad idea to call virtual methods from constructors, as the body of the B constructor hasn't been run yet, so it's only half-initialized. I've had a few situations where this is a pain, but if you tell us what you're trying to achieve we may be able to come up with something cleaner.
You can check what the type is which is being instantiated:
public A()
{
var theType = this.GetType(); // will be typeof(B) in your example
}
But acessing the instance (e.g. it's properties) is probably not wise, since the derived type is not yet initialized when the base type's constructor is executing.