C#强制静态字段初始化
我们目前正在实现某种基于字符串的“可扩展枚举类”。下面只显示了C代码的一部分,以使问题更容易理解 如果我运行下面的代码,它会将“BaseValue1”和“BaseValue2”写入控制台 如果我取消注释RunClassConstructor行并运行代码,它会将“DerivedValue1”和“DerivedValue2”另外写入控制台。C#强制静态字段初始化,c#,enums,static,initialization,C#,Enums,Static,Initialization,我们目前正在实现某种基于字符串的“可扩展枚举类”。下面只显示了C代码的一部分,以使问题更容易理解 如果我运行下面的代码,它会将“BaseValue1”和“BaseValue2”写入控制台 如果我取消注释RunClassConstructor行并运行代码,它会将“DerivedValue1”和“DerivedValue2”另外写入控制台。 这就是我想要实现的,但是我不想使用RunClassConstructor行来实现它 我认为,DerivedEnum.allkey会触发“DerivedValue
这就是我想要实现的,但是我不想使用RunClassConstructor行来实现它 我认为,DerivedEnum.allkey会触发“DerivedValue1”和“DerivedValue2”的创建,但显然不是这样 有没有可能实现我想要的,而不强迫这些“枚举类”的用户编写一些神奇的代码,或者进行某种虚拟初始化
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
public class Program
{
static void Main()
{
//System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DerivedEnum).TypeHandle);
foreach (var value in DerivedEnum.AllKeys)
{
Console.WriteLine(value);
}
}
}
public class BaseEnum
{
private static readonly IDictionary<string, BaseEnum> _dictionary = new Dictionary<string, BaseEnum>();
public static ICollection<string> AllKeys
{
get
{
return _dictionary.Keys;
}
}
public static readonly BaseEnum BaseValue1 = new BaseEnum("BaseValue1");
public static readonly BaseEnum BaseValue2 = new BaseEnum("BaseValue2");
protected BaseEnum(string value)
{
_dictionary[value] = this;
}
}
public class DerivedEnum : BaseEnum
{
public static readonly DerivedEnum DerivedValue1 = new DerivedEnum("DerivedValue1");
public static readonly DerivedEnum DerivedValue2 = new DerivedEnum("DerivedValue2");
protected DerivedEnum(string value)
: base(value)
{
}
}
}
使用系统;
使用System.Collections.Generic;
命名空间控制台应用程序
{
公共课程
{
静态void Main()
{
//System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DerivedEnum.TypeHandle);
foreach(DerivedEnum.AllKeys中的变量值)
{
控制台写入线(值);
}
}
}
公共类BaseEnum
{
私有静态只读IDictionary _dictionary=new dictionary();
公共静态ICollection所有密钥
{
得到
{
返回_dictionary.Keys;
}
}
公共静态只读BaseEnum BaseValue1=新BaseEnum(“BaseValue1”);
公共静态只读BaseEnum BaseValue2=新BaseEnum(“BaseValue2”);
受保护的BaseEnum(字符串值)
{
_字典[值]=这个;
}
}
公共类DerivedEnum:BaseEnum
{
公共静态只读DerivedEnum DerivedValue1=新的DerivedEnum(“DerivedValue1”);
公共静态只读DerivedEnum DerivedValue2=新的DerivedEnum(“DerivedValue2”);
受保护的DerivedEnum(字符串值)
:基准(值)
{
}
}
}
静态构造函数仅在首次访问类时调用
虽然您使用了DerivedEnum.AllKeys
,但它只是从BaseEnum
继承的。因此,DerivedEnum
从未被直接引用
您可以做的一点小技巧是在DerivedEnum
上创建一个新的static
属性,该属性从基类返回相同的属性,因此当调用该属性时,将调用派生类的静态构造函数
public class DerivedEnum : BaseEnum
{
public new static ICollection<string> AllKeys
{
get
{
return BaseEnum.AllKeys;
}
}
}
您还可以使用此代码初始化在其他程序集中定义的派生类:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.DefinedTypes)
.Where(x => typeof(BaseEnum).IsAssignableFrom(x))
.ToList().ForEach(x => System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(x.TypeHandle));
在C#中,静态成员在第一次使用类之前初始化。在您的示例中,您实际上使用了基类BaseEnum
的一个成员,并绕过了DerivedEnum
,这只会导致BaseEnum
的静态成员被初始化
您需要在派生类中实现AllKeys
属性。这将确保编译器使用派生类中的属性&初始化它的所有成员
然后在DerivedEnum中添加一个新的AllKeys
属性,以覆盖BaseEnum
的AllKeys
new public static ICollection<string> AllKeys
{
get
{
return BaseEnum.AllKeys;
}
}
新建公共静态ICollection所有键
{
得到
{
返回BaseEnum.AllKeys;
}
}
,因此您需要实例化DerivedEnum
或访问其静态成员之一。谢谢。是否还有一种只需修改BaseEnum
的解决方案,这样DerivedEnum
的实现者就不必注意实现新的静态属性?可能不知道,因为BaseEnum
不知道它的所有派生类…您也可以使用System.reflection
动态调用它们查看我的更新。好的,如果所有派生类都与BaseEnum
类位于同一个Dll中,这将是一个很好的解决方案。在我的代码中,不幸的是情况并非如此,因为我们库的用户可能会在其他DLL中添加自己的派生类。谢谢您的回复。我猜你的意思是AllKeys
属性,而不是AllKeys
字段,对吗?@MaDev正确,谢谢你指出这一点。我会更新答案。
new public static ICollection<string> AllKeys
{
get
{
return BaseEnum.AllKeys;
}
}