为什么我不能继承静态类?
为什么我不能继承静态类?
静态类的成员通过类型名称进行访问,例如:
MyStaticType.MyStaticMember();
如果允许继承静态类,那么你必须通过新的类型名称进行访问:
MyNewType.MyStaticMember();
因此,新的类型在代码中与原始类型没有任何关系。这样就无法利用继承关系来实现多态等功能。
也许你只是想扩展原始类中的某些项。在这种情况下,你可以在完全新的类型中使用原始类的成员。
也许你想为现有的静态类型添加方法。你可以通过扩展方法来实现。
也许你想能够在运行时将静态Type
传递给函数,并调用该类型的方法,而不知道这个方法具体做什么。在这种情况下,你可以使用接口。
因此,从继承静态类中并没有真正获益。
你不能通过扩展方法向现有的静态类型添加方法。请参阅我的评论,了解所需用法的示例。(基本上,你只需将原来命名为MyNewType的内容重命名为MyStaticType,即MyStaticType: OldProject.MyStaticType)
可以通过定义静态类型和虚拟静态成员之间的继承关系来让SomeClass<T> where T:Foo
可以访问Foo
的成员。如果T
是一个覆盖了Foo
的某些虚拟静态成员的类,那么泛型类将使用这些覆盖。甚至可以定义一种约定,通过这种约定,语言可以以与当前CLR兼容的方式实现这一点(例如,具有这些成员的类应定义一个包含这些实例成员的受保护的非静态类,以及一个静态字段,其中包含该类型的实例)。
我发现自己有一个情况,我认为继承静态类是正确的做法,尽管你当然可以通过其他方式访问它们。我有一个用于将原始数据流发送到打印机的静态类(用于与工业标签打印机通信)。它有一堆Windows API声明。现在我发现自己正在编写另一个用于操作打印机的类,它需要相同的API调用。合并?不好。重复声明?丑陋。继承?好,但不允许。
为什么不能继承静态类?
静态类不能被继承的主要原因是它们是抽象和密封的(这也防止了任何实例被创建)。
所以,下面的代码:
static class Foo { }
编译成下面的IL代码:
.class private abstract auto ansi sealed beforefieldinit Foo extends [mscorlib]System.Object { }
可以看到,静态类被实现为抽象加密封。这回答了“为什么静态类是密封的”这个问题。但他想知道的是为什么这样做,为什么要将静态类设为密封的。
这个回答并没有完全回答问题,只是重申了他所问的问题。
好吧,提问者应该问的是“为什么静态类是密封的”,而不是“为什么我不能继承静态类”,后者的回答当然是“因为它们是密封的”。这个回答得到了我的支持。
感谢分享静态类会自动编译为密封类的信息——我一直在想这是如何发生的,何时发生的!
这个回答是正确的,但就像告诉一个迷路的人“你在我面前”一样无用,当他们问你“我在哪里”的时候。
同时,在C#中无法创建抽象密封类。所以为什么会有这样的矛盾。还没有找到一个好的解释。阅读这个:stackoverflow.com/questions/19404589/…
这是问题,不是答案。
这个回答可能不是正确或完整的答案,但至少是一个答案。
各位,说明一个门上的锁是什么类型并不能回答为什么要锁门的原因。问题的结尾提到了语言设计者而不是实现者,进一步强调了他在问为什么要做这个决定,而不是如何实现。当然,如何实现也是有信息价值的,如果为什么问题也得到了回答的话。
为什么不能继承静态类?
这实际上是按设计来的。似乎没有什么好的理由去继承静态类。你总是可以通过类名本身来访问它的公共静态成员。我所见过的唯一继承静态内容的原因是一些不好的原因,比如为了节省一些输入字符。
可能有理由考虑将静态成员直接引入作用域中的机制(在Orcas产品周期之后我们将考虑这一点),但是静态类继承不是正确的方法:这是错误的机制,只适用于恰好位于静态类中的静态成员。(Mads Torgersen, C#语言PM)
其他来自channel9的观点:
.NET中的继承仅基于实例。静态方法是在类型级别而不是实例级别上定义的。这就是为什么静态方法/属性/事件不能重写的原因。
静态方法在内存中只保存一次。它们不会创建虚拟表等。
如果在.NET中调用实例方法,你总是会给它当前的实例。这是由.NET运行时隐藏的,但确实发生了。每个实例方法都有一个指向该方法正在运行的对象的指针(引用)作为第一个参数。但是静态方法没有这样的情况发生(因为它们在类型级别上定义)。编译器如何决定选择要调用的方法?
作为一个有价值的想法,littleguru提供了这个问题的一个部分解决方法:单例模式。
至于你的第一个引用,你可以将一个实例类强制转换为基类,然后使用其公共成员。
Torgersen真的缺乏想象力。我有一个很好的理由想要这样做 🙂
你怎么看?你有一个dll,它不是开源的/你没有它的源代码,比如NUnit。你想要扩展它的Assert类,使其拥有一个像Throws<>(Action a)这样的方法(是的,这也是有的,但在某个时候并不是)。你可以添加一个Assert:NUnit.Framework.Assert类到你的项目中,然后添加一个Throws方法。问题解决了。在代码中使用起来更加简洁...不需要想出另一个类名并记住那个类名,只需键入Assert.并查看可用的方法。
这可以通过为静态类编写扩展方法来解决。不需要继承。
无法为静态类编写扩展方法。stackoverflow.com/questions/249222
当然。你在这里误解了我。我的意思是,所描述的用户场景所需的功能可能在未来仅仅通过允许为静态类添加扩展方法来提供。不需要静态继承。这就是为什么他的场景对我来说不是一个很好的引入静态继承的理由。如果C#在这方面进行修改,为什么要进行重大的重新设计,当一个小的重新设计在实践中同样好。
对于“一切都是对象”的线程:stackoverflow.com/questions/436211
为什么不能继承静态类的主要原因是静态类的成员是在类型级别而不是实例级别上定义的,并且静态方法在内存中只保存一次,没有为它们创建虚拟表。解决这个问题的一种方法是使用单例模式来实现相似的功能。