Nee*_*eed 6 c# static-constructor
码:
class Base<T,U> where T:Base<T,U>,new() where U :class
{
protected static U _val = null;
internal static void ShowValue()
{
if(_val == null)new T(); //Without this line, it won't work as expected
Console.WriteLine (_val);
}
internal static void Virtual()
{
Console.WriteLine ("Base");
}
}
class Deriv :Base<Deriv,string>
{
static Deriv()
{
_val = "some string value";
}
internal static new void Virtual ()
{
Console.WriteLine ("Deriv");
}
}
public static void Main (string[] args)
{
Deriv.ShowValue();
Deriv.Virtual();
}
Run Code Online (Sandbox Code Playgroud)
由于.NET的泛型,我可以创建一堆特定的类,重用通用基类中定义的泛型静态方法.它可以在一定程度上模仿继承多态性.但是为了初始化不同版本的静态字段,我要使用静态构造函数.不幸的是,我们无法直接调用它们,因此,我们必须找到一种方法来触发它的调用.上面给出的例子显示了一种方法.但我不喜欢实例化或反射方法.我们也不能对泛型参数的静态方法进行约束.所以,我想问一下,如果还有其他办法可以做这种工作!
先谢谢!
~~~~~~~~~~~~~~~~
一些结论(也许有点早):
似乎没有解决方法来处理这种情况.我必须实例化一个子类或使用反射.考虑到.cctors只需要调用一次,我赞成反射方法,因为在某些情况下,new()约束不是一个选择 - 就像你不应该将无参数ctor暴露给用户.
在进行进一步的实验之后,我发现.cctors可以被多次调用,但只有第一次调用才会影响静态字段的设置.这很奇怪,但很奇怪!
class MyClass
{
static int _val = 0;
static MyClass()
{
_val++;
Console.WriteLine (_val);
}
}
public static void Main (string[] args)
{
ConstructorInfo ci = typeof(MyClass).TypeInitializer;
ci.Invoke(new object[0]);
ci.Invoke(new object[0]);
ci.Invoke(new object[0]);
}
//result:
//1
//1
//1
//1
Run Code Online (Sandbox Code Playgroud)
我强烈建议你重新考虑你的设计.尝试将这种解决方法用于"静态继承"是针对.NET的一些核心设计.
目前还不清楚你要解决的是什么更大的问题,但尝试这样的"聪明"代码来模拟继承会导致代码在较长时期内难以维护和诊断.
如果没有实际使用Deriv(或创建它的实例)的成员,您基本上不会触发静态构造函数.重要的是要了解Deriv.ShowValue()基本上转换为调用
Base<Deriv, string>.ShowValue();
Run Code Online (Sandbox Code Playgroud)
......所以你实际上并没有打电话Deriv.如果以这种方式编写,您的调用代码实际上会更清晰.
编辑:另一个(显然不幸)明确避免使用类型初始化程序的原因是.NET 4.5中存在一个错误,导致在某些情况下不正确地抛出异常.有关详细信息,请参阅有关该主题的问题.
静态构造函数是自动的,仅一次。你不能自己打电话给他们。
public class Bus
{
// Static constructor:
static Bus()
{
System.Console.WriteLine("The static constructor invoked.");
}
public static void Drive()
{
System.Console.WriteLine("The Drive method invoked.");
}
}
class TestBus
{
static void Main()
{
Bus.Drive();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
The static constructor invoked.
The Drive method invoked.
Run Code Online (Sandbox Code Playgroud)