tags:

views:

96

answers:

7

I keep getting StackOverFlowException whenever I instantiate an instance of A class. I know it has got something to do with the fact that A.b field is of type derived from class A. But why would that cause an exception?

static void Main(string[] args)
{
     A a = new A(); // exception
}

class A 
{
    private B b = new B();
}

class B:A {}

thank you

+1  A: 

Because A has a reference to a class B, which derives from A. Due to constructor chaining, the ctor of B calls the ctor of A, leading to a creation of a new instance of B, which will continue until eternity or a StackOverflowException.

Femaref
+5  A: 

Because B is inherited from A, each time you're creating an A, a B is created, which, in turn creates another B. You've essentially created an endless loop of class creation.

Robaticus
+1  A: 

Its because constructors are called recursively

Amitabh
A: 

When you create an instance of A, it will create an internal instance of B.... which will - guess what - create an internal instance of B which will - guess what - create an internal instance of B which will - guess what - create an internal instance of B.

This is because the B constructor goes on the A constructor which is recursive. Stack overflow.

TomTom
+4  A: 

Here is what is happening under the hood

  1. Create a new instance of A
  2. As a consequence it creates an instance of B for the private field b
  3. B derives from A and hence has it's own field b. At this point it goes back to step #2 and repeats until a stack overflow occurs
JaredPar
Since same exception is also thrown if I try to initialize A.b field inside A's constructor, I assume that only way around this is to not initialize A.b field at all?
flockofcode
+1  A: 

Because you ave a circular reference

in order to make a B you have to make an A In order to Make an A you have to Make an B

As such it tunnels downwards.

To fix it, dont initialise the private field.

John Nicholas
+1  A: 

If you want your subclass to know about any derivative types, use generics. This is featured heavily in the CSLA.NET Framework.

public class A<T> where T : A<T>
{

}

public class B : A<B>
{

}

Note that A doesn't reference B, but you get to encapsulate the derived type at base level on methods etc.

Adam
I've tried instantiating your code, but it doesn't work --> A<A<B>> a = new A<A<B>>();
flockofcode
Sorry, in all places I use this little pattern the base class is abstract - you instantiate and use B, not A<B>. I've just tried A<B> b = new A<B>(); where B is derived from A, and this works. You get only the base class reference.
Adam