为什么C#在默认情况下将方法实现为非虚拟方法?

为什么C#在默认情况下将方法实现为非虚拟方法?,c#,java,.net,virtual-functions,C#,Java,.net,Virtual Functions,与Java不同,为什么C#在默认情况下将方法视为非虚拟函数?这更可能是绩效问题而不是其他可能的结果吗 我记得读过Anders Hejlsberg的一段话,谈到了现有体系结构带来的几个优势。但是,副作用呢?默认情况下,非虚拟方法是否真的是一个很好的折衷方案?< P> C是受C++影响的(以及更多)。默认情况下,C++不能启用动态调度(虚拟函数)。一个(好的?)论点是这样一个问题:“您多久实现一次属于类层次结构的类?”。默认情况下避免启用动态调度的另一个原因是内存占用。没有指向的虚拟指针(vpoin

与Java不同,为什么C#在默认情况下将方法视为非虚拟函数?这更可能是绩效问题而不是其他可能的结果吗

我记得读过Anders Hejlsberg的一段话,谈到了现有体系结构带来的几个优势。但是,副作用呢?默认情况下,非虚拟方法是否真的是一个很好的折衷方案?

< P> C是受C++影响的(以及更多)。默认情况下,C++不能启用动态调度(虚拟函数)。一个(好的?)论点是这样一个问题:“您多久实现一次属于类层次结构的类?”。默认情况下避免启用动态调度的另一个原因是内存占用。没有指向的虚拟指针(vpointer)的类当然比启用后期绑定的相应类小

性能问题不是那么容易回答“是”或“否”。原因是实时(JIT)编译,这是C#中的一种运行时优化

关于“

类的另一个类似问题应该设计为继承,以便能够利用它。默认情况下,使用方法
virtual
意味着类中的每个函数都可以插入并替换为另一个函数,这并不是一件好事。许多人甚至认为类在默认情况下应该是密封的


virtual
方法也可能有轻微的性能影响。然而,这不太可能是主要原因。

因为很容易忘记方法可能被重写,而不是为此而设计的。C#让你在虚拟化之前思考。我认为这是一个伟大的设计决策。一些人(比如Jon Skeet)甚至说,类应该默认密封。

总结一下其他人的说法,有几个原因:

在C++中,有很多语法和语义的东西直接来自C++。默认情况下,C++中不虚虚的方法影响了C<./p> 2-默认情况下让每个方法都是虚拟的是一个性能问题,因为每个方法调用都必须使用对象的虚拟表。此外,这严重限制了实时编译器内联方法和执行其他类型优化的能力

3-最重要的是,如果默认情况下方法不是虚拟的,则可以保证类的行为。当它们在默认情况下是虚拟的时,例如在Java中,您甚至不能保证一个简单的getter方法会按预期的那样执行,因为它可以被重写以在派生类中执行任何操作(当然,您可以并且应该使该方法和/或类成为最终的)


正如Zifre所提到的,人们可能会想,为什么C语言没有更进一步,在默认情况下使类密封。这是关于实现继承问题的整个辩论的一部分,这是一个非常有趣的话题。

简单的原因是设计和维护成本以及性能成本。与非虚拟方法相比,虚拟方法具有额外的成本,因为类的设计者必须计划当该方法被另一个类重写时会发生什么。如果您希望某个特定的方法更新内部状态或具有特定的行为,那么这会产生很大的影响。现在,您必须计划当派生类更改该行为时会发生什么。在这种情况下,编写可靠的代码要困难得多


使用非虚拟方法,您可以完全控制。任何出错的事情都是原作者的错。代码更容易推理

这当然不是性能问题。Sun的Java解释器使用相同的代码进行分派(
invokevirtual
bytecode),HotSpot生成的代码无论是否为
final
,都完全相同。我相信所有C#对象(但不是结构)都有虚拟方法,所以您总是需要
vtbl
/runtime类标识。C#是一种“类Java语言”的方言。建议它来自C++不是完全诚实的。 有一种想法是,你应该“为继承而设计,否则就禁止继承”。这听起来是个不错的主意,直到你有一个严重的商业案例需要快速解决。可能是从您无法控制的代码继承而来。

如果所有的C#方法都是虚拟的,那么vtbl会大得多

如果类定义了虚拟方法,则C#对象只有虚拟方法。的确,所有对象都具有包含vtbl等效项的类型信息,但是如果没有定义虚拟方法,则只会出现基本对象方法


Tom Hawtin:更准确的说法是C++、C和java都是C语言家族的一部分:

< p>我很惊讶这里似乎有一种共识,即默认的非虚是做事情的正确方式。我会站在篱笆的另一边,我想是务实的

对我来说,大多数的理由都像古老的“如果我们给你权力,你可能会伤害你自己”的论据。来自程序员

在我看来,那些不知道(或没有足够的时间)为继承性和/或可扩展性设计库的程序员,正是那些产生了我可能需要修复或调整的库的程序员——正是覆盖功能最有用的库

我不得不编写难看的、绝望的变通代码(或者放弃使用并推出自己的替代解决方案)的次数,因为我无法覆盖的次数远远超过了我曾经被覆盖的次数(例如在Java中),因为我覆盖了设计者可能没有考虑到的地方

默认情况下,非虚拟会让我的生活更加艰难

更新:有人[非常正确地]指出我实际上没有回答这个问题。s