我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。
但是我似乎不能为静态类声明继承。
就像这样:
public static class Base
{
}
public static class Inherited : Base
{
}
不会起作用。
为什么语言的设计者们拒绝了这种可能性呢?
我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。
但是我似乎不能为静态类声明继承。
就像这样:
public static class Base
{
}
public static class Inherited : Base
{
}
不会起作用。
为什么语言的设计者们拒绝了这种可能性呢?
当前回答
当创建只包含静态成员和私有构造函数的静态类时。唯一的原因是静态构造函数阻止类被实例化,因为我们不能继承静态类。访问静态类成员的唯一方法是使用类名本身。试图继承静态类并不是一个好主意。
其他回答
不能继承静态类的主要原因是它们是抽象且密封的(这也阻止了创建它们的任何实例)。
所以这个:
static class Foo { }
编译到这个IL:
.class private abstract auto ansi sealed beforefieldinit Foo
extends [mscorlib]System.Object
{
}
嗯…如果你只是用静态方法填充非静态类,情况会有很大不同吗?
引用本文:
This is actually by design. There seems to be no good reason to inherit a static class. It has public static members that you can always access via the class name itself. The only reasons I have seen for inheriting static stuff have been bad ones, such as saving a couple of characters of typing. There may be reason to consider mechanisms to bring static members directly into scope (and we will in fact consider this after the Orcas product cycle), but static class inheritance is not the way to go: It is the wrong mechanism to use, and works only for static members that happen to reside in a static class. (Mads Torgersen, C# Language PM)
来自9频道的其他观点
Inheritance in .NET works only on instance base. Static methods are defined on the type level not on the instance level. That is why overriding doesn't work with static methods/properties/events... Static methods are only held once in memory. There is no virtual table etc. that is created for them. If you invoke an instance method in .NET, you always give it the current instance. This is hidden by the .NET runtime, but it happens. Each instance method has as first argument a pointer (reference) to the object that the method is run on. This doesn't happen with static methods (as they are defined on type level). How should the compiler decide to select the method to invoke? (littleguru)
作为一个有价值的想法,littleuru对这个问题有一个部分的“变通方案”:单例模式。
可以这样考虑:你通过类型名访问静态成员,就像这样:
MyStaticType.MyStaticMember();
如果你要从这个类继承,你必须通过新的类型名来访问它:
MyNewType.MyStaticMember();
因此,在代码中使用时,新项与原始项没有关系。没有办法利用任何继承关系来处理多态性之类的事情。
也许您只是想扩展原始类中的一些项。在这种情况下,没有什么可以阻止您在一个全新的类型中使用原始类型的成员。
也许您希望向现有静态类型添加方法。您已经可以通过扩展方法做到这一点。
也许您希望能够在运行时将静态类型传递给函数,并调用该类型的方法,而不需要确切地知道该方法的功能。在这种情况下,您可以使用接口。
所以,最终你不会从继承静态类中获得任何东西。
你可以做一些看起来像静态继承的事情。
诀窍是这样的:
public abstract class StaticBase<TSuccessor>
where TSuccessor : StaticBase<TSuccessor>, new()
{
protected static readonly TSuccessor Instance = new TSuccessor();
}
然后你可以这样做:
public class Base : StaticBase<Base>
{
public Base()
{
}
public void MethodA()
{
}
}
public class Inherited : Base
{
private Inherited()
{
}
public new static void MethodA()
{
Instance.MethodA();
}
}
Inherited类本身不是静态的,但是我们不允许创建它。它实际上继承了用于构建Base的静态构造函数,并且Base的所有属性和方法都是静态的。现在要做的唯一一件事就是为需要公开到静态上下文的每个方法和属性制作静态包装器。
它也有缺点,比如需要手动创建静态包装器方法和new关键字。但是这种方法有助于支持一些与静态继承非常相似的东西。
注: 我们使用它来创建已编译查询,这实际上可以用ConcurrentDictionary代替,但是具有线程安全性的静态只读字段就足够了。