当第一次访问静态类是基类上的静态方法时,为什么我的静态对象没有被实例化?

djd*_*d87 2 c# static-methods static-classes c#-4.0

我有以下课程:

public class DocketType : Enumeration<DocketType, int, string>
{
    public static DocketType ChangeOver = new DocketType(1, "Changeover");
    public static DocketType Withdrawal = new DocketType(2, "Withdrawal");
    public static DocketType Installation = new DocketType(3, "Installation");

    private DocketType(int docketTypeId, string description) 
        : base(docketTypeId, description)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

使用以下基类:

public abstract class Enumeration<TEnum, X, Y> : IComparable 
    where TEnum : Enumeration<TEnum, X, Y> 
    where X : IComparable 
    where Y : IComparable
{        
    protected Enumeration(X value, Y displayName)
    {
        AddToStaticCache(this);
    }
    public static TEnum Resolve(X value)
    {
        return Cache[value] as TEnum;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是Changeover,WithdrawalInstallation当在第一时间,静态类用于经由不被创建Resolve在基类方法.即如果我打电话Resolve,那么Cache将是空的.

但是,如果我执行类似DocketType foo = DocketType.Changeover;的操作Application_Start,则会创建所有静态字段,然后Cache具有所有三个值.

创建这些静态字段的正确方法是什么,以便此方案有效?

Tim*_*mwi 7

我不认为当你访问的所有字段都DocketType 应该被初始化Enumeration<>.您DocketType致电时根本没有引用该类型Enumeration<>.Resolve().每次访问静态方法或静态字段时,CLR是否应该真正初始化所有子类?它会减慢您的代码速度,在大多数情况下会不必要地减慢代码速度.

您可以尝试编写Docket.Resolve(),C#允许您这样做,但我不知道这是否会编译成与以前不同的东西; 编译器可能只是把它变成了Enumeration<DocketType, int, string>.Resolve(),你又回到了sqaure.

说实话,我倾向于建议您的代码结构存在缺陷,而您遇到的问题就是这种情况的症状.你不应该依赖Cache包含某些东西.当您不使用该类型时,您不必依赖某些静态类型初始化.

因此,您的选择是:

  • DocketTypeMain()方法中的某处进行无意义的引用以确保初始化发生,并且认为您的代码结构可能存在缺陷.
  • 将静态字段移动到另一种类型(可能是Enumeration<>其自身),这样可以缓解缺陷但不能完全解决它.
  • 考虑代码的基本结构并重新设计它,这样您就不必依赖缓存.