Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#强制静态字段初始化_C#_Enums_Static_Initialization - Fatal编程技术网

C#强制静态字段初始化

C#强制静态字段初始化,c#,enums,static,initialization,C#,Enums,Static,Initialization,我们目前正在实现某种基于字符串的“可扩展枚举类”。下面只显示了C代码的一部分,以使问题更容易理解 如果我运行下面的代码,它会将“BaseValue1”和“BaseValue2”写入控制台 如果我取消注释RunClassConstructor行并运行代码,它会将“DerivedValue1”和“DerivedValue2”另外写入控制台。 这就是我想要实现的,但是我不想使用RunClassConstructor行来实现它 我认为,DerivedEnum.allkey会触发“DerivedValue

我们目前正在实现某种基于字符串的“可扩展枚举类”。下面只显示了C代码的一部分,以使问题更容易理解

如果我运行下面的代码,它会将“BaseValue1”和“BaseValue2”写入控制台

如果我取消注释RunClassConstructor行并运行代码,它会将“DerivedValue1”和“DerivedValue2”另外写入控制台。
这就是我想要实现的,但是我不想使用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;
    }
}