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

问题

与Java不同,为什么C#默认将方法视为非虚函数?是否更可能是性能问题而不是其他可能的结果?

我想起了阅读Anders Hejlsberg的一段有关现有架构带来的几个优点的内容。但是,副作用呢?默认情况下使用非虚方法真的是一个很好的权衡吗?


#1 热门回答(95 赞)

应该为继承设计类以便能够利用它。默认使用methodsvirtual意味着类中的每个函数都可以被插入并被另一个函数替换,这实际上并不是一件好事。许多人甚至认为默认情况下课程应该是sealed

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


#2 热门回答(82 赞)

我很惊讶这里似乎有这样的共识,即非虚拟默认是正确的做事方式。我会在另一方面下台 - 我认为实用主义的一面。

大多数理由都像旧的"如果我们给你力量,你可能会伤害自己"这样的论点。来自程序员?!

在我看来,编码人员不够了解(或有足够的时间)设计他们的图书馆用于继承和/或可扩展性的编码器是完全生成我可能需要修复或调整的库 - 完全是库中哪些覆盖能力最有用。

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

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

**更新:**我已经指出[非常正确]我实际上没有回答这个问题。所以 - 并为迟到而道歉......

我有点想写一些简洁的东西,比如"C#默认情况下将方法实现为非虚拟方法,因为做出了一个错误的决定,它比程序员更重视程序"。 (我认为基于这个问题的其他一些答案 - 比如性能(过早优化,任何人?),或者保证类的行为,这可能有点合理。)

但是,我意识到我只是在陈述我的观点而不是Stack Overflow所希望的那个明确的答案。当然,我认为,在最高级别,最终(但无益)的答案是:

默认情况下,它们是非虚拟的,因为语言设计者决定制作,这就是他们所选择的。

现在我猜他们做出决定的确切原因我们永远不会......哦,等等!The transcript of a conversation!

因此,似乎这里关于覆盖API的危险和明确设计继承的必要性的答案和评论都在正确的轨道上,但都缺少一个重要的时间方面:Anders主要担心的是维护一个类或API的隐含contractacross版本。我认为他实际上更关心的是允许.Net / C#平台在代码下进行更改,而不是担心平台上的用户代码更改。 (而他的"务实"观点与我的完全相反,因为他从另一边看。)

(但他们不能只选择虚拟默认,然后通过代码库填写"最终"吗?也许这并不完全相同......而Anders显然比我聪明,所以我会让它撒谎。)


#3 热门回答(15 赞)

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