为什么我不能继承静态类?

Use*_*ser 216 c# inheritance static

我有几个不需要任何州的课程.从组织的角度来看,我想把它们放到层次结构中.

但似乎我无法为静态类声明继承.

像这样的东西:

public static class Base
{
}

public static class Inherited : Base
{
}
Run Code Online (Sandbox Code Playgroud)

不管用.

为什么语言的设计者会关闭这种可能性?

boj*_*boj 168

来自这里的引文:

这实际上是设计的.似乎没有充分的理由继承静态类.它有公共静态成员,您始终可以通过类名本身访问它们.我看到继承静态内容的唯一原因是糟糕的,例如保存几个字符的输入.

可能有理由考虑将静态成员直接引入范围的机制(事实上我们将在Orcas产品周期之后考虑这一点),但静态类继承不是要走的路:它是错误的使用机制,并且有效仅适用于碰巧驻留在静态类中的静态成员.

(Mads Torgersen,C#语言PM)

来自channel9的其他意见

.NET中的继承仅适用于实例库.静态方法是在类型级别上定义的,而不是在实例级别上定义的.这就是为什么覆盖不适用于静态方法/属性/事件...

静态方法只在内存中保存一次.没有为它们创建的虚拟表等.

如果在.NET中调用实例方法,则始终为其提供当前实例.这是.NET运行时隐藏的,但它确实发生了.每个实例方法都将第一个参数作为运行该方法的对象的指针(引用).静态方法不会发生这种情况(因为它们是在类型级别定义的).编译器应该如何决定选择要调用的方法?

(littleguru)

作为一个有价值的想法,littleguru对此问题有一个部分"解决方法":Singleton模式.

  • 真的,对Torgersen来说缺乏想象力.我有一个很好的理由想要这样做:) (90认同)
  • 这个怎么样?你有一个不是开源的dll /你没有访问它的源代码,让我们说NUnit.你想扩展它的Assert类,让它有一个类似Throws <>(Action a)的方法(是的,那也是,但有一点它不是.)你可以向你的项目添加一个Assert:NUnit.Framework.Assert类,然后添加一个Throws方法.问题解决了.在代码中使用它也更干净......而不是必须提出另一个类名并记住该类名,只需键入Assert即可.并查看可用的方法. (10认同)
  • @Learner那不太公平.在.Net**中,所有**都继承自`object`,每个人都应该知道这一点.所以静态类**总是**继承自`object`,无论你是否明确指定它. (5认同)
  • 请你分享一下吗? (4认同)
  • @KonradMorawski编写静态类的扩展方法是不可能的.http://stackoverflow.com/questions/249222/can-i-add-extension-methods-to-an-existing-static-class (4认同)
  • @modiX当然.你在这里误解了我.我的意思是,可以通过允许静态类的扩展方法来提供user420667描述的场景中所需的功能(**将来**).不需要静态继承.这就是为什么他的场景没有把我作为引入静态继承的一个非常好的理由.如果要在这方面对C#进行修改,那么为什么要在重大设计中进行重大设计,而在实践中同样重要. (2认同)

And*_*are 70

您不能继承静态类的主要原因是它们是抽象的和密封的(这也可以防止创建它们的任何实例).

所以这:

static class Foo { }
Run Code Online (Sandbox Code Playgroud)

汇编到这个IL:

.class private abstract auto ansi sealed beforefieldinit Foo
  extends [mscorlib]System.Object
 {
 }
Run Code Online (Sandbox Code Playgroud)

  • 那么,OP应该问"为什么静态类是密封的",而不是"为什么我不能继承静态类?",答案当然是*"因为它们是密封的"*.这个答案得到了我的投票. (27认同)
  • 这并没有回答所有问题; 它只是重述了他所询问的问题. (22认同)
  • @AlexBudovski:这个答案是正确的,但当他们问你"我在哪里"时,作为一个告诉失落的人"你在我面前"是无用的. (20认同)
  • 你说静态是实现为抽象+密封.他想知道*为什么*这样做了.为什么密封? (16认同)
  • 感谢分享静态类自动编译为密封类 - 我想知道如何/何时发生! (6认同)

Joe*_*orn 24

这样考虑一下:通过类型名称访问静态成员,如下所示:

MyStaticType.MyStaticMember();
Run Code Online (Sandbox Code Playgroud)

如果您继承该类,则必须通过新类型名称访问它:

MyNewType.MyStaticMember();
Run Code Online (Sandbox Code Playgroud)

因此,当在代码中使用时,新项目与原始项目没有关系.对于像多态这样的东西,没有办法利用任何继承关系.

也许您认为您只想扩展原始课程中的一些项目.在这种情况下,没有什么可以阻止您只使用全新类型的原始成员.

也许您想要将方法添加到现有的静态类型中.您可以通过扩展方法完成此操作.

也许你希望能够通过一个静态的Type在运行时函数,调用一个方法上的类型,不知道该方法做什么.在这种情况下,您可以使用接口.

所以,最后你并没有从继承静态类中获得任何东西.

  • 您无法通过扩展方法将方法添加到现有静态类型.请参阅我对所接受答案的评论,以获得所需的示例.(基本上你只想将你命名为MyNewType的名称重命名为MyStaticType,所以MyStaticType:OldProject.MyStaticType) (5认同)
  • 可以定义与静态类型和虚拟静态成员的继承关系,使得一个`SomeClass <T>,其中T:Foo`可以访问`Foo`的成员,如果`T`是一个覆盖一些虚拟静态成员的类对于`Foo`,泛型类将使用这些覆盖.甚至可能定义一种约定,通过该约定,语言可以以与当前CLR兼容的方式执行此操作(例如,具有此类成员的类应定义包含此类实例成员的受保护非静态类以及静态字段持有该类型的实例). (2认同)