在 C# 中初始化静态字段以用于枚举模式
我的问题实际上是关于解决 C# 如何初始化静态字段的方法。我需要这样做,以尝试复制 Java 样式枚举。以下是显示问题的代码示例:
我所有枚举要继承的基类
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);
}
}
枚举集的示例:
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) {}
}
这就是问题所在:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("color value of 1 is " + Colors.ValueOf(2)); //fails here
}
}
上面的代码失败,因为 EnumBase.ValueMap 包含零项,因为尚未调用 Color 的任何构造函数。
看起来这应该不难做到,在Java中是可能的,我觉得我一定在这里遗漏了一些东西?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这种模式基本上行不通。拥有一个字典也不是一个好主意 - 我怀疑你想让你的
EnumBase
抽象和通用:然后可以有一个受保护的静态成员可以通过每个派生类有效地“发布”:
这会强制您访问 Color 类本身...此时,由于静态初始化程序,字段将被初始化。
不幸的是,要使所有这些工作顺利进行,还有很多事情要做:(
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:That could then have a protected static member which can be effectively "published" through each derived class:
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 :(
我相信您在代码中尝试说的很简单:
您可以使用反射轻松读取 Description 属性。如果您愿意,您甚至可以为 Colors 枚举创建一个扩展方法,并实现类似于 ValueOf 的方法作为扩展方法
I believe what you were trying so say in code is simply:
You can easily read the Description attribute using reflection.. You can even create an extention methods for the Colors enums if you want and implement something similar to ValueOf as an extention method
您错过了静态成员的要点。静态成员是类型的成员,而不是实例的成员。
当您调用 Colors.ValueOf() 时,您仅访问该类型,尚未创建该类型的实例 - 根本不会调用实例构造函数。
如果您只想定义一些行为,您可以为
Color
枚举创建一个扩展方法。您只需从int
基进行转换即可从值中获取枚举:您还可以在
System.Enum
类中找到许多有用的方法 (http:// /msdn.microsoft.com/en-us/library/system.enum.aspx)。有一些方法可以从string
进行解析或获取所有可能的enum
值的集合。You're missing the point of a static member. A static member is a member of the type, not the instance.
When you call
Colors.ValueOf()
you are only accessing the type, an instance has not been created of that type - the instance constructors won't be called at all.You could create an extension method for the
Color
enum if you just want to be able to define some behaviours. You could get the enum from a value simply by casting from itsint
base:You'll also find a number of useful methods in the
System.Enum
class (http://msdn.microsoft.com/en-us/library/system.enum.aspx). There are methods there to parse fromstring
or to get a collection of all the possibleenum
values.这是可以做到的,而且实际上是非常有用的。设置变量时您可以获得类型安全以及动态搜索的能力。我希望在子类中看到更少的代码,但无论如何,它运行良好。您还可以对此进行扩展并增加 EnumBase 中的字段数量,还可以覆盖运算符和 ToString 方法等。您还可以将更多泛型放入其中。这是类固醇的枚举。
已编辑:阅读条目底部
EnumBase:
颜色:
用法:
已编辑:
如果您多次从 EnumBase 继承,则上述代码将不起作用(这是一个大问题) 。静态方法不是继承的,即所有子类只会向静态基类字典添加更多记录。
如果用例足够强大,您可以重用代码而不是尝试使用继承:
This can be done, and it is actually quite useful. You get type safety when setting variables and the ability to search dynamically. I'd prefer to see less code in the child class, but none the less, it works well. You could also expand upon this and grow the number of fields in the EnumBase and also override operators and the ToString methods, etc. You could also throw more generics into the mix. It's Enums on steroids.
Edited: Read bottom of entry
EnumBase:
Colors:
Usage:
Edited:
The above code doesn't work if you inherit from EnumBase more than once (which is a huge problem). The static methods aren't inherited, i.e. all child classes will just add more records to the static base class Dictionary.
If the use case is strong enough, you can reuse the code instead of trying to use inheritance: