Bur*_*gan 105 .net c# java virtual-functions
与Java不同,为什么C#默认将方法视为非虚函数?它更可能是性能问题而不是其他可能的结果吗?
我想起了Anders Hejlsberg的段落,内容是现有架构带来的几个优点.但是,副作用呢?默认情况下使用非虚方法真的是一个很好的权衡吗?
Meh*_*ari 98
应该为继承设计类以便能够利用它.其方法virtual在默认情况下意味着,在每类功能,可以插入和更换另一个,这是不是一个真正的好东西.很多人甚至认为课程应该是sealed默认的.
virtual方法也可能有轻微的性能影响.然而,这可能不是主要原因.
mwa*_*rdm 89
我很惊讶这里似乎有这样的共识,即非虚拟默认是正确的做事方式.我会在另一方面下台 - 我认为实用主义的一面.
大多数理由都像旧的"如果我们给你力量,你可能会伤到自己"这样的论点.来自程序员?!
在我看来,编码人员不够了解(或有足够的时间)设计他们的库以进行继承和/或可扩展性的编码器是完全生成我可能需要修复或调整的库 - 完全是库中的覆盖能力最有用.
我必须编写丑陋,绝望的解决方案代码(或放弃使用并推出我自己的替代解决方案)的次数,因为我无法超越,远远超过我被咬过的次数(例如在Java中)通过覆盖设计者可能没有考虑过的地方.
非虚拟默认让我的生活更加困难.
更新:有人指出[非常正确]我实际上没有回答这个问题.所以 - 并为迟到而道歉......
我有点想写一些简洁的东西,比如"C#默认情况下将方法实现为非虚拟,因为做出了一个错误的决定,它比程序员更重视程序".(我认为根据这个问题的其他一些答案 - 比如性能(过早优化,任何人?),或保证类的行为,这可能有点合理.)
但是,我意识到我只是在陈述我的意见,而不是Stack Overflow所希望的那个明确的答案.当然,我认为,在最高级别,最终(但没有帮助)的答案是:
默认情况下,它们是非虚拟的,因为语言设计者决定制作,这就是他们所选择的.
现在我想他们做出决定的确切原因我们永远不会......哦,等等! 谈话的成绩单!
因此,似乎这里关于重写API的危险和明确设计继承的必要性的答案和评论都在正确的轨道上,但都缺少一个重要的时间方面:Anders的主要关注点是维护一个类或API的隐含跨版本合同.而且我认为他实际上更关心的是允许.Net/C#平台在代码下进行更改,而不是担心平台上的用户代码更改.(而他的"务实"观点与我的完全相反,因为他从另一边看.)
(但他们不能只选择虚拟默认,然后通过代码库填写"最终"吗?也许这并不完全相同......而Anders显然比我聪明,所以我会让它撒谎.)
Tri*_*ian 12
总结其他人所说的,有几个原因:
1-在C#中,语法和语义有很多东西直接来自C++.事实上,C++中默认情况下不是虚拟的方法影响了C#.
2-默认情况下,每个方法都是虚拟的,这是一个性能问题,因为每个方法调用都必须使用对象的虚拟表.此外,这极大地限制了Just-In-Time编译器内联方法和执行其他类型优化的能力.
3-最重要的是,如果默认情况下方法不是虚拟的,则可以保证类的行为.当它们在默认情况下是虚拟的时,例如在Java中,你甚至不能保证简单的getter方法会按预期执行,因为它可以被覆盖以在派生类中执行任何操作(当然,你可以而且应该,方法和/或类最终).
正如Zifre所提到的,人们可能会想,为什么C#语言没有更进一步,默认情况下会使类密封.这是关于实现继承问题的整个辩论的一部分,这是一个非常有趣的话题.
C#受C++(及更多)的影响.默认情况下,C++不启用动态分派(虚拟功能).对此的一个(好的?)论点是这样一个问题:"你多久实现一个属于类层次结构成员的类?".默认情况下避免启用动态分派的另一个原因是内存占用.没有指向虚拟表的虚拟指针(vpointer)的类比使用后期绑定的相应类小.
性能问题并不容易说"是"或"不".原因是Just In Time(JIT)编译,它是C#中的运行时优化.
关于" 虚拟通话速度...... "的另一个类似问题
除了性能成本之外,简单的原因是设计和维护成本.与非虚方法相比,虚方法具有额外的成本,因为类的设计者必须计划当方法被另一个类重写时发生的事情.如果您希望特定方法更新内部状态或具有特定行为,则会产生很大影响.您现在必须计划派生类更改该行为时会发生什么.在那种情况下编写可靠的代码要困难得多.
使用非虚拟方法,您可以完全控制.任何出错的都是原作者的错.代码更容易推理.
| 归档时间: |
|
| 查看次数: |
12791 次 |
| 最近记录: |