I have some nested classes, BaseOuter
and BaseInner
, and child classes DerivedOuter
and DerivedInner
. BaseOuter
has property BaseInner baseInner;
, and when I instantiate DerivedOuter
I want the runtime type of baseInner
property to be DerivedInner
.
I first solved this like I have below, using a virtual initializer to instantiate baseInner
, that is overriden in DerivedOuter
. That allows me to do baseInner = new BaseInner();
vs baseInner = new DerivedInner();
in the respective initializers.
After noticing a Resharper warning and doing a little more reading I decided I should change it... but how?
A couple of things come to mind. I could call the initializer after calling the constructor, requiring calling code to do var baseOuter = new BaseOuter(); baseOuter.Initialize();
. I can probably use a factory, but I'd have to think about that a little. Lastly, perhaps there is a design flaw in the class-nesting I want to do?
It's worth pointing out that doing new BaseInner();
is expensive, and I don't simply want to create it and throw it away.
using System;
public class Program
{
public static void Main()
{
Console.WriteLine("new BaseOuter");
var baseOuter = new BaseOuter();
Console.WriteLine("\nnew DerivedOuter");
var derivedOuter = new DerivedOuter();
}
class BaseOuter{
protected BaseInner baseInner;
public BaseOuter(){
Console.WriteLine("BaseOuter Constructor");
/* lots of stuff I want in derived class */
// This is an anti-pattern I want to avoid
//https://www.jetbrains.com/help/resharper/2018.2/VirtualMemberCallInConstructor.html
InitializeInner();
}
protected virtual void InitializeInner(){
Console.WriteLine(" BaseOuter Initialize BaseInner");
baseInner = new BaseInner();
}
protected class BaseInner{
public int x;
public BaseInner(){
/* stuff that is needed in DerivedInner too */
Console.WriteLine(" BaseInner Constructor");
x = 2;
}
}
}
class DerivedOuter : BaseOuter {
public DerivedOuter() {
Console.WriteLine("DerivedOuter Constructor (finished)");
}
protected override void InitializeInner(){
Console.WriteLine(" DerivedOuter Initialize DerivedInner");
baseInner = new DerivedInner();
}
protected class DerivedInner : BaseInner {
public double y;
public DerivedInner(){
Console.WriteLine(" DerivedInner Constructor");
y = 2d;
}
}
}
}
Output
new BaseOuter
BaseOuter Constructor
BaseOuter Initialize BaseInner
BaseInner Constructor
new DerivedOuter
BaseOuter Constructor
DerivedOuter Initialize DerivedInner
BaseInner Constructor
DerivedInner Constructor
DerivedOuter Constructor (finished)
All of the code can be found here in this .NET Fiddle.