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

发布于 2024-09-14 05:02:54 字数 1159 浏览 7 评论 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)
    {
    }
}

使用以下基类:

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;
    }
}

我遇到的问题是,当第一次使用静态类是通过基类中的 Resolve 方法。即,如果我调用Resolve,则Cache将为空。

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

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

I have the following class:

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)
    {
    }
}

With the following base class:

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;
    }
}

The problem I have is that Changeover, Withdrawal and Installation are not being created when the first time that the static class is used is via the Resolve method in the base class. I.e. if I call Resolve, then Cache will be empty.

However, if I do something like DocketType foo = DocketType.Changeover; in Application_Start, then all of the static fields get created and then Cache has all three values.

What's the correct way to create these static fields so this scenario works?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鸠书 2024-09-21 05:02:54

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

您可以尝试编写 Docket.Resolve(),C# 允许您这样做,但我不知道这是否会编译成与以前不同的东西;编译器可能只是将其转换为 Enumeration.Resolve(),然后您就回到了平方。

老实说,我倾向于认为您的代码结构存在缺陷,而您遇到的问题就是这种缺陷的症状。您不必依赖包含某些内容的Cache。当您不使用该类型时,您不必依赖于某些静态类型初始化。

因此,您的选择是:

  • Main() 方法中的某处放置对 DocketType 的毫无意义的引用,以确保初始化发生,并接受您的代码结构可能是这样的想法:有缺陷的。
  • 将静态字段移至另一种类型,也许是 Enumeration<> 本身,这可以减轻该缺陷,但并不能完全解决它。
  • 考虑代码的基本结构并重新设计它,以便您不必依赖于已填充的缓存。

I don’t think the fields in DocketType should be initialised when all you’re accessing is Enumeration<>. You are not referencing the DocketType type at all when you call Enumeration<>.Resolve(). Should the CLR really initialise all subclasses every time you access a static method or static field? It would slow down your code, and in most cases unnecessarily so.

You could try writing Docket.Resolve(), which C# allows you to do, but I don’t know whether this will compile into something different than before; the compiler might just turn it into Enumeration<DocketType, int, string>.Resolve() and you’re back to sqaure one.

To be honest, I am inclined to suggest that your code structure is flawed, and the problem you’re running into is a symptom of that. You shouldn’t have to rely on Cache containing something. You shouldn’t have to rely on some static type initialisation to have occurred when you’re not using that type.

Therefore, your options are:

  • Put a pointless reference to DocketType somewhere in your Main() method to ensure the initialisation happens, and live with the idea that your code structure may be flawed.
  • Move the static fields to another type, perhaps Enumeration<> itself, which alleviates the flaw but doesn’t completely solve it.
  • Think about the fundamental structure of your code and redesign it so that you don’t have to rely on the cache being filled.
梦纸 2024-09-21 05:02:54

编辑:我没有意识到您曾经提到过基本类型。这肯定有问题 - 在这种情况下,无法保证运行 DocketType 的类型初始值设定项。我以为您正在调用 DocketType 中的方法,然后该方法使用了缓存。

在这种情况下,以前的方法也行不通。据我所知,使用类型作为泛型类型参数不会强制类型初始化,而这正是您所追求的。

我想你会很难让它发挥作用。基本上你想引发类型初始化,但我不知道这样做的好方法。您可以使用反射调用类型初始值设定项,但必须非常小心,只能执行一次。

我同意 Timwi 的观点:我认为最好的解决方案是重组你的设计,这样你就不需要这个了。

EDIT: I didn't realise that you were only ever referring to the base type. That definitely has problems - nothing is guaranteed to run the type initializer for DocketType in that case. I thought you were calling a method in DocketType which then used the cache.

In this case, it wouldn't have worked before, either. Using a type as a generic type argument doesn't force type initialization as far as I'm aware, and that's what you're after.

I think you'll have a hard time getting this to work. Basically you want to provoke type initialization, and I don't know a good way of doing that. You can call the type initializer with reflection, but you'd have to be very careful to only do that once.

I agree with Timwi: I think your best solution would be to restructure your design so you don't need this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文