【发布时间】:2011-03-01 04:09:45
【问题描述】:
我从this answer 了解到,C# 静态字段初始值设定项“在第一次使用该类的静态字段之前执行……”但这仍然会产生我没想到的结果,至少对于泛型类型.
来自 Java 世界,我想念我丰富的枚举,我认为使用 C# 的更重要的泛型,我应该能够用最少的样板来复制它们。这里(去掉了一些细节,比如可比性)是我想出的:
public class AbstractEnum<T> where T : AbstractEnum<T>
{
static readonly IDictionary<String, T> nameRegistry = new Dictionary<String, T>();
readonly String name;
protected AbstractEnum (String name)
{
this.name = name;
nameRegistry[name] = (T) this;
}
public String Name {
get {
return name;
}
}
public static T ValueOf(String name) {
return nameRegistry[name];
}
public static IEnumerable<T> Values {
get {
return nameRegistry.Values;
}
}
}
还有一些示例子类:
public class SomeEnum : AbstractEnum<SomeEnum> {
public static readonly SomeEnum V1 = new SomeEnum("V1");
public static readonly SomeEnum V2 = new SomeEnum("V2");
SomeEnum(String name) : base(name) {
}
}
public class OtherEnum : AbstractEnum<OtherEnum> {
public static readonly OtherEnum V1 = new OtherEnum("V1");
public static readonly OtherEnum V2 = new OtherEnum("V2");
OtherEnum(String name) : base(name) {
}
}
这看起来不错,而且或多或少有诀窍...除了按照规范的字母,实际实例(SomeEnum.V1、OtherEnum.V1 等)不会被初始化,除非至少有一个它们被明确提及。基类中的静态字段/方法不计算在内。因此,例如,以下内容:
Console.WriteLine("Count: {0}", SomeEnum.Values.Count());
foreach (SomeEnum e in SomeEnum.Values) {
Console.WriteLine(e.Name);
}
写Count: 0,但如果我添加以下行--
Console.WriteLine("SomeEnum.V1: " + SomeEnum.V1.Name);
-- 甚至 以上,我得到:
Count: 2
V1
V2
(顺便提一下,在静态构造函数中初始化实例没有区别。)
现在,我可以通过将nameRegistry 标记为protected 并将Values 和ValueOf 推入子类来解决此问题,但我希望保持超类中的所有复杂性并将样板保持在最低限度。任何 C#-fu 优于我的人都可以想出一个使子类实例“自动执行”的技巧吗?
注意:FWIW,这是 Mac OS 上的 Mono。 YM 在 MS .NET 上,在 Windows 上,MV。
预计到达时间: 对于单语 C# 开发人员(甚至是经验仅限于以“C”开头的语言的多语言开发人员)想知道我正在尝试做的 WTF:this。 C# 枚举负责类型安全问题,但它们仍然缺少其他所有内容。
【问题讨论】:
-
你不能让这个可靠,放弃这个想法。
-
当你说“放弃这个想法”时,究竟是哪一部分?因为我需要具有行为的枚举类型;这不会消失。
-
什么行为对枚举有意义?您列出的所有内容都使用 Enum 类上的静态方法存在。
标签: c# generics initialization