Note: This article was edited after a Gonçalo Lopes presented me with a better solution. Thanks!
Every now and then you run into a situation where you wish your programming language of choice was just a tad more flexible than it actually is.
For example, constructors in C# always have to directly call one of the base type constructors as the first thing they do (or do they? keep reading).
Yesterday I ran into a situation where I would like my derived class to always use the same implementation* for a certain injectable dependency. No problem:
public class FooBase
{
public FooBase(IDependency dependency) { /* stuff here */ }
}
public class MyFoo : FooBase
{
public MyFoo() : base(new MyDependency()) { }
}
The dependency is created on the fly and my base class constructor is happy. However, my derived class also needed to make use of this dependency and my base class does not expose any property or field for me to access it. So before calling the base constructor, I would have liked to store a reference to this newly created MyDependency object.
If we switch to Java syntax for a moment, it would be something like this:
public class MyFoo
{
private MyDependency _dependency;
public MyFoo()
{
// Note that this is not actually valid in Java either.
// The call to super must be the first statement in the constructor.
_dependency = new MyDependency();
super(myDependency);
}
}
Now, the reason why this isn't allowed makes perfect sense. We'd be accessing a field of this type before the base constructor is initialized, but for technical reasons the compiler is enforcing initialization to occur from base type to more specialized types. Now, I'm not an expert at compiler creation, but I think this would have been perfectly fine to allow the use of local variables:
public MyFoo()
{
MyDependency dependency = new MyDependency();
super(myDependency);
_dependency = dependency;
}
It even seems like a easy enough thing to let the compiler to automatically park the reference on the stack temporarily, but alas.
My original workaround
So far I've neglected to mention a lesser known feature of C#, which is to include a method call in the base constructor call:
public class MyFoo : FooBase
{
public MyFoo() : base(CreateDependency())
{
}
private static IDependency CreateDependency()
{
return new MyDependency();
}
}
This code is essentially identical to the first code snippet. If you were paying attention, you noticed that the method I'm calling is static. This is again to prevent access to fields prior to initialization of the base type. So how does this help me? Well, originally I wrote something like this:
// =========================
// Warning: evil code inside
// =========================
public class MyFoo: FooBase
{
private static IDependency _tempDependency;
private readonly IDependency _dependency;
public MyFoo() : base(CreateDependency())
{
_dependency = _tempDependency;
_tempDependency = null;
Monitor.Exit(typeof(MyFoo));
}
private static IDependency CreateDependency()
{
Monitor.Enter(typeof(MyFoo));
_tempDependency = new MyDependency();
return _tempDependency;
}
}
The locks in here (Monitor.Enter and Monitor.Exit) are just in case you'd be mass creating these objects in multiple threads. Performance wouldn't be good, but at least it would be error free. Use of ThreadStaticAttribute would be another option.
A better solution
Using the code above seemed like a very bad idea. Luckily, there was a better solution to my presented problem, as Gonçalo Lopes pointed out after I posted the original article: Just use a private constructor to both create an object and put it on the stack:
public class MyFoo : FooBase
{
public MyFoo() : this(new MyDependency()) { }
public MyFoo(IDependency dependency) : base(dependency)
{
_dependency = dependency;
}
}
Wrapping up
In the end, I didn't actually need any nasty workarounds, which I'm really glad about.
Trying to solve the problem once again made me aware of this ability to call static methods before the base constructor however, which has plenty of other uses. You could do string manipulation, constructing complex object structures in a more readable fashion, code reuse, etc.
*: That doesn't sound very Liskov, does it? The reality is a bit different, but it is beside the point of this post.