My question is actually about a way to work around how C# initializes static fields. I need to do this, in my attempt to duplicate a Java style enum. The following is an example of the code that shows the problem:
A base class for all my enums to inherit from
public class EnumBase
{
private int _val;
private string _description;
protected static Dictionary<int, EnumBase> ValueMap = new Dictionary<int, EnumBase>();
public EnumBase(int v, string desc)
{
_description = desc;
_val = v;
ValueMap.Add(_val, this);
}
public static EnumBase ValueOf(int i)
{
return ValueMap[i];
}
public static IEnumerable<EnumBase> Values { get { return ValueMap.Values; } }
public override string ToString()
{
return string.Format("MyEnum({0})", _val);
}
}
A sample of an enumerated set:
public sealed class Colors : EnumBase
{
public static readonly Colors Red = new Colors(0, "Red");
public static readonly Colors Green = new Colors(1, "Green");
public static readonly Colors Blue = new Colors(2, "Blue");
public static readonly Colors Yellow = new Colors(3, "Yellow");
public Colors(int v, string d) : base(v,d) {}
}
This is where the problem is:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("color value of 1 is " + Colors.ValueOf(2)); //fails here
}
}
The above code fails because EnumBase.ValueMap contains zero items, because none of the constructors for Color have been called yet.
It seems like this shouldn't be that hard to do, it is possible in Java, I feel like I must be missing something here?
That pattern basically isn't going to work. Having a single dictionary isn't going to be a good idea, either - I suspect you want to make your EnumBase abstract and generic:
public abstract class EnumBase<T> where T : EnumBase<T>
That could then have a protected static member which can be effectively "published" through each derived class:
public abstract class EnumBase<T> where T : EnumBase<T>
{
protected static T ValueOfImpl(int value)
{
...
}
}
public class Color : EnumBase<Color>
{
// static fields
// Force initialization on any access, not just on field access
static Color() {}
// Each derived class would have this.
public static Color ValueOf(int value)
{
return ValueOfImpl(value);
}
}
This then forces you to access the Color class itself... at which point the fields will be initialized, due to the static initializer.
There are quite a few things to be done to make all of this work, unfortunately :(
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With