Static constructors + inheritence
Argh, I implemented today a wicked thing:
public abstract class BaseClass
{
protected static Item[] _items = null;
public static string[] GetAllCodes()
{
string[] codes = new string[_items.Length];
for(int i = 0 ; i < _items.Length; i++)
{
codes[i] = _items[i];.Code;
}
return codes;
}
}
public class InheriredClass :BaseClass {
public static readonly SomeThing1 = "1";
public static readonly SomeThing2 = "2";
static InheriredClass () {
_items = new Item[2];
_items[0] = new Item("1",SomeThing1 );
_items[1] = new Item("2",SomeThing2 );
}
}
I just wanted BaseClass to handle all my processing and lookup functions and in the derived class just to prepare the items in the static constructor. I even wrote a unit test to ensure that everyting worked, as I expected. But it appeared that when I call InheriredClass .GetAllCodes() I am out of luck, because the static constructor of InheriredClass has not run and _items is still null.
If I access, for example, InheriredClass.SomeThing1 before calling InheriredClass .GetAllCodes() , then the static constructor gets called and everything is fine. By chance, my first unit-test accessed one of the static fields, so when I ran all of the tests, they went green, but when I ran them one-by-one a few blushed in red :)
Argh, I should have not been messing with static constructors + inheritence, but now I am determined to find how the compiler works and come-up with an elegant solutions. It was easy to find something on the topic but now I have to explore it. I believe in the saying "When things don't work as you expect and you don't put the effort to find why, then the time you spend on finding the problem is just wasted!"



3 Comments:
This behavior is natural since when you are accessing the readonly field you are actually executing the static constructor of InheritedClass. Every field initialization goes in a constructor. If you call GetAllCodes() directly, without accessing the readonly fields first, the static constructor of InheritedClass never gets executed, because BaseClass is not aware of its derivates.
You can implement GetAllCodes in InheritedClass like this:
public new static string[] GetAllCodes()
{
return BaseClass.GetAllCodes();
}
This will ensure that the static constructor is executed.
By
Martin Kulov, at
10 March, 2005 02:26
Yeap, this is the problem. The confusing thing is that somewhere I read:
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
An instance of the class is created.
Any of the static members of the class are referenced.
Take a look at the second case. It is a bit confusing that when I call InhertitedClass.SomeMethod its static constructor is not fired.
But since there is no clean workaround, I refactored the solution. Now BaseClass is not static at all, and InheritedClass uses singleton pattern to enforce static semantics
By
Ivan Mitev, at
10 March, 2005 10:26
>> Take a look at the second case. It is a bit confusing that when I call InhertitedClass.SomeMethod its static constructor is not fired.
It does get fired! However in your code you only access the base’s class static method, not the inherited one. With the sample method that I wrote about the static constructor does get fired when you access the static method.
By
Martin Kulov, at
11 March, 2005 02:05
Post a Comment
<< Home