静态构造函数调用两次

时间:2017-03-19 23:35:24

标签: c# arrays list constructor static

之前我有一个static TopUp()方法,我想用Baseclass的静态构造函数替换它,因为它只执行一次"正如msdn所述 msdn: Static Constuctor
保留派生类的任何解决方案'在构造函数中初始化并只执行一次?

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

2 个答案:

答案 0 :(得分:2)

您的静态构造仅被调用一次。每种类型一次,即。

每次使用不同类型参数的BaseClass<T>时,这都是完全不同的类型。因此,继承Junction<byte>的{​​{1}}与BaseClass<byte>的类型不同。调用BaseClass<object>的静态构造函数,以及BaseClass<byte>的静态构造函数。

从你的问题来看,你真正想要实现的是什么并不是很清楚。我会说,在静态构造函数中使用BaseClass<object>强烈暗示你的类根本不是通用的。 Junction<byte>的任何其他用途仍然必须依赖BaseClass<T>,因此Junction<byte>。这可能会否定你认为通过使类通用而获得的任何好处。

您可以通过将静态构造函数移动到BaseClass<byte>继承的非泛型基类来强制执行一次。 E.g:

BaseClass<T>

但鉴于课堂上缺乏通用性,我们并不清楚这会有多大帮助。这里似乎存在一个应该解决的更广泛的设计缺陷。

答案 1 :(得分:1)

问题是您在类型基类中拥有静态初始值设定项。问题是BaseClass<string>BaseClass<int>被认为是两种不同的类型。实际的类是在编译时生成的,因此编译器会为每个变体复制静态初始化程序。

如果您更改静态初始值设定项中的最后一行以包含该类型的名称,您将能够更好地了解此问题。

在.Net 4.6中,你可以这样做:

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

在.Net 4.0或更高版本中,您可以执行此操作:

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

要解决您的问题,请在没有type参数的标准类中进行静态初始化。在这种情况下,您只需从BaseClass中删除<T>类型参数即可。例如:

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