RBr*_*g99 8 c# virtual inheritance static
每当我读到RE这个问题或静态继承的类似主题时,回复通常都是不支持的(我们知道),原因是因为这是一个糟糕的设计并且可能有更好的方法做到这一点.我很想找到一个更好的方法,所以我愿意接受所有的建议 - 这就是我想做的事情.
我有一个没有实例数据的类.所有方法都是静态的.我们称之为class BaseStatic.我现在想要一个新的静态类(当然好几个但是坚持一个)继承自这个静态类并添加一些新的静态方法,让我们调用它SubStatic.
我希望消费者能够写的是:
SubStatic.MethodFromSub();
Run Code Online (Sandbox Code Playgroud)
并且
SubStatic.MethodFromBase();
Run Code Online (Sandbox Code Playgroud)
我知道我也可以写:
BaseStatic.MethodFromBase()
Run Code Online (Sandbox Code Playgroud)
显式,但消费者必须知道哪个类实现了哪些方法.我不能用继承来做这个,因为我不能从另一个继承一个静态类.那么有什么更好的方法呢?
现在,我知道我能有这些类的实例类,我可以定义的所有方法静态 - 这会给我我上面描述,但会导致其他问题,即行为:
当我这样做:SubStatic.MethodFromBase()在SubStatic不调用静态构造函数,因为该方法在父类的静态运行(父的静态构造函数被调用)
如果静态父方法之一,需要调用该子类可以覆盖另一种方法,我需要在子类中的虚拟静态方法.我知道我不能拥有.
显然糟糕的设计 - 任何人都可以帮我重做吗?我知道我可以使用实例继承并正确使用虚方法(我已经让它以这种方式工作)但客户端代码总是必须创建一个实例(或者我想一些单例).
这可以满足您的目的,尽管我当然会包括一些异常处理,并伴随其实现提供大量关于其工作原理和方式的文档。
当 的 静态构造函数Base运行(一次)时,当前加载到应用程序域中的所有程序集都会被编目,并选择从Base. 迭代这些,我们运行静态构造函数。但值得注意的是,这不再保证每个实现的 cctor 将恰好运行一次,必须向每个实现添加逻辑才能重新做出该断言。Base此外,在运行cctor for 后加载的类型不会通过调用中的方法来初始化Base
要模拟虚拟方法,请使用new关键字隐藏基方法。您可以通过使用声明类的名称来限定它来调用基方法(就像B示例中的类一样)
using System;
using System.Linq;
using System.Runtime.CompilerServices;
namespace ConsoleApplication6
{
public class Base
{
static Base()
{
Console.WriteLine("Base cctor");
var thisType = typeof (Base);
var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes());
var derivations = loadedTypes.Where(thisType.IsAssignableFrom);
foreach(var derivation in derivations)
{
RuntimeHelpers.RunClassConstructor(derivation.TypeHandle);
}
}
public static void Foo()
{
Console.WriteLine("Bar");
}
}
public class A : Base
{
static A()
{
Console.WriteLine("A cctor");
}
}
public class B : Base
{
static B()
{
Console.WriteLine("B cctor");
}
public new static void Foo()
{
Console.WriteLine("Bar!!");
Base.Foo();
}
}
class Program
{
static void Main()
{
Console.WriteLine("A:");
A.Foo();
Console.WriteLine();
Console.WriteLine("B:");
B.Foo();
Console.WriteLine();
Console.WriteLine("Base:");
Base.Foo();
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
另一种选择在于 CRTP(或 C# 范例中的 CRGP)或奇怪的重复模板(通用)参数模式
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication6
{
public class Base<T>
where T : Base<T>
{
static Base()
{
RuntimeHelpers.RunClassConstructor(typeof (T).TypeHandle);
}
public static void Foo()
{
Console.WriteLine("Bar");
}
}
public class Base : Base<Base>
{
}
public class A : Base<A>
{
static A()
{
Console.WriteLine("A cctor");
}
}
public class B : Base<B>
{
static B()
{
Console.WriteLine("B cctor");
}
public new static void Foo()
{
Console.WriteLine("Bar!!");
Base<B>.Foo();
}
}
class Program
{
static void Main()
{
Console.WriteLine("A:");
A.Foo();
Console.WriteLine();
Console.WriteLine("B:");
B.Foo();
Console.WriteLine();
Console.WriteLine("Base:");
Base.Foo();
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当我们调用静态方法时,A我们实际上是在调用它,而它与orBase<A>不同,因此我们实际上可以确定该方法是如何调用的并运行适当的 cctor。Base<B>Base