简体   繁体   English

静态构造函数调用两次

[英]Static constructor called twice

Previously I've had a static TopUp() method what I wanted to substitute with the Baseclass's static constructor, because it's "performed once only" as the msdn states. 以前我有一个static TopUp()方法,我想用Baseclass的静态构造函数替换它,因为它只是像msdn一样“只执行一次”。
msdn: Static Constuctor msdn:静态构造函数
Any solution for keep the derived classes' initialization in the constructor and perform it only once? 用于将派生类的初始化保留在构造函数中并仅执行一次的任何解决方案?

class BaseClass<T>
{
    static BaseClass()
    {
        for (byte i = 0; i < 2; i++)
        {
            var temp = new Junction<byte>[2] { new Level2<byte>(), new OtherLevel2<byte>() };
            Program.myList.Add(temp);
        }
        Console.WriteLine("static BaseClass()");
    }
}

abstract class Junction<T> : BaseClass<T> { }

sealed class Level2<T> : Junction<T> { }

sealed class OtherLevel2<T> : Junction<T> { }

class Program
{
    internal static List<Junction<byte>[]> myList = new List<Junction<byte>[]>();
    static Program()
    {
        BaseClass<object> callTheStaticMethod = new BaseClass<object>();
    }

    static void Main()
    {
        Console.WriteLine("myList.Count = " + myList.Count);
        Console.ReadLine();
    }
}

Output:  
static BaseClass()  
static BaseClass()  
myList.Count = 4

Your static construction is called only once. 您的静态构造调用一次。 Once per type, that is. 每种类型一次,即。

Each time you use your BaseClass<T> with a different type parameter, that's a completely different type. 每次使用带有不同类型参数的BaseClass<T>时,这都是完全不同的类型。 So, Junction<byte> , which inherits BaseClass<byte> , is a different type from BaseClass<object> . 因此,继承BaseClass<byte> Junction<byte>是与BaseClass<object>不同的类型。 The static constructor for BaseClass<byte> is called, as well as the static constructor for BaseClass<object> . 调用BaseClass<byte>的静态构造函数,以及BaseClass<object>的静态构造函数。

It's not really clear from your question what it is you're actually trying to achieve. 从你的问题来看,你真正想要达到的目标并不是很清楚。 I will say, that the use of Junction<byte> in the static constructor strongly suggests that your class is not really generic at all. 我会说,在静态构造函数中使用Junction<byte>强烈地表明你的类根本不是通用的。 Any other use of BaseClass<T> is necessarily still dependent on Junction<byte> , and thus BaseClass<byte> . BaseClass<T>任何其他用法仍然必须依赖于Junction<byte> ,因此BaseClass<byte> And this probably negates whatever benefit you thought you were going to get by making the class generic. 这可能会否定你认为通过使类具有通用性而获得的任何好处。

You can force the static constructor to execute only once by moving it to a non-generic base class inherited by BaseClass<T> . 您可以通过将静态构造函数移动到BaseClass<T>继承的非泛型基类来强制执行一次。 Eg: 例如:

class BaseClass { /* static constructor here */ }
class BaseClass<T> : BaseClass { /* other stuff */ }

But given the lack of generic-ness in the class to start with, it's not clear that this will really help much. 但鉴于课堂上缺乏通用性,目前尚不清楚这对真的有多大帮助。 There seems to be a broader design flaw here that should be addressed. 这里似乎存在一个应该解决的更广泛的设计缺陷。

The issue is that you have the static initializer in a typed base class. 问题是您在类型化的基类中有静态初始化程序。 The issue is that BaseClass<string> and BaseClass<int> are considered two different types. 问题是BaseClass<string>BaseClass<int>被认为是两种不同的类型。 The actual classes are generated at compile time, and so the compiler duplicates the static initializer for each variation. 实际的类是在编译时生成的,因此编译器会为每个变体复制静态初始化程序。

If you change the last line in the static initializer to include the name of the type you'll be able to get a better idea of this issue. 如果您更改静态初始值设定项中的最后一行以包含该类型的名称,您将能够更好地了解此问题。

In .Net 4.6 you can do this: 在.Net 4.6中,您可以这样做:

Console.WriteLine($"static BaseClass<{nameof(T)}>()");

In .Net 4.0 or later you can do this: 在.Net 4.0或更高版本中,您可以执行以下操作:

string typeName = typeof(T).FullName;
Console.WriteLine(string.Format("static BaseClass<{0}>()", typeName));

To resolve your issue, do your static initialization in a standard class that does not have a type parameter. 要解决您的问题,请在没有类型参数的标准类中执行静态初始化。 In this case, you can simply remove the <T> type parameter from the BaseClass. 在这种情况下,您只需从BaseClass中删除<T>类型参数即可。 Example: 例:

class BaseClass
{
    static BaseClass()
    {
        for (byte i = 0; i < 2; i++)
        {
            var temp = new Junction<byte>[2] { new Level2<byte>(), new OtherLevel2<byte>() };
            Program.myList.Add(temp);
        }

        Console.WriteLine($"static BaseClass<{nameof(T)}>()");
    }
}

abstract class Junction<T> : BaseClass { }

sealed class Level2<T> : Junction<T> { }

sealed class OtherLevel2<T> : Junction<T> { }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM