Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么C#中的方法不是自动虚拟的?_C#_Virtual - Fatal编程技术网

为什么C#中的方法不是自动虚拟的?

为什么C#中的方法不是自动虚拟的?,c#,virtual,C#,Virtual,可能重复: 定义哪些方法不可重写而哪些方法不可重写要少得多,因为(至少对我来说),在设计类时,你不在乎它的继承者是否会重写你的方法 那么,为什么C#中的方法不是自动虚拟的呢?这方面的常识是什么?因此很清楚您是允许覆盖还是强制隐藏方法(通过新建关键字) 强制添加关键字可以消除任何可能存在的歧义。约定?我想没别的了。我知道Java会自动使方法虚拟化,而C#不会,所以在某种程度上,对于什么更好,显然存在一些分歧。就个人而言,我更喜欢C++默认——认为重写方法比不重写方法要少得多,因此,明确地定义虚拟

可能重复:

定义哪些方法不可重写而哪些方法不可重写要少得多,因为(至少对我来说),在设计类时,你不在乎它的继承者是否会重写你的方法


那么,为什么C#中的方法不是自动虚拟的呢?这方面的常识是什么?

因此很清楚您是允许覆盖还是强制隐藏方法(通过
新建
关键字)


强制添加关键字可以消除任何可能存在的歧义。

约定?我想没别的了。我知道Java会自动使方法虚拟化,而C#不会,所以在某种程度上,对于什么更好,显然存在一些分歧。就个人而言,我更喜欢C++默认——认为重写方法比不重写方法要少得多,因此,明确地定义虚拟方法看起来更简洁。

您应该注意在派生类中可以重写哪些成员。< /P>
决定哪些方法是虚拟的应该是一个经过深思熟虑的决定——而不是自动发生的事情——与关于API公共界面的任何其他决定一样。

除了设计和清晰性原因之外,非虚拟方法在技术上也更好,原因如下:

  • 调用虚拟方法需要更长的时间(因为运行时需要在虚拟查找表中导航以找到要调用的实际方法)
  • 虚拟方法无法内联(因为编译器在编译时不知道最终将调用哪个方法)

因此,除非您有特定的意图覆盖该方法,否则最好是非虚拟的。

实际上,这是一种糟糕的设计实践。我的意思是,不管哪些方法是可重写的,哪些方法不是。你应该<强>永远/强>想想应该和应该超越的能力,就像你应该仔细考虑应该或不应该公开一样。 我认为存在一个效率问题以及其他人发布的原因。如果方法不是虚拟的,则无需花费cpu周期来查找重写。

当有人从您的类继承时,这将使他们能够在基类使用任何方法时更改其工作方式。如果您有一个方法,您绝对需要它在基类中以某种方式执行操作,那么您将无法不允许某人更改该功能

这里有一个例子。假设您有一个不希望返回错误的函数。有人进来并决定更改它,以便在周二抛出一个超出范围的异常。现在基类中的代码失败了,因为它所依赖的东西发生了变化。

因为它不是Java


说真的,只是一种不同的支持哲学。Java希望扩展性是默认的,封装是显式的,C希望扩展性是显式的,封装是默认的。

Anders Hejlsberg在中回答了这个问题,我引用:

有几个原因。一是 演出我们可以这样观察 人们用Java编写代码,却忘记了 将他们的方法标记为最终结果。 因此,这些方法是虚拟的。 因为它们是虚拟的,所以它们不是 表现也很好。只是 与性能相关的性能开销 作为一种虚拟的方法。那是一个 问题

一个更重要的问题是版本控制。 关于这个问题,有两个学派 虚拟方法。学术学校 思想的中心说:“一切都应该 虚拟的,因为我可能想 总有一天会推翻它 思想流派,来自 构建在中运行的真实应用程序 “现实世界,”他说,“我们必须 对我们的产品要非常小心 虚拟的。”

当我们在一个虚拟的 平台,我们做了很多 关于未来发展的承诺 未来。对于非虚方法,我们 答应我当你打电话的时候 方法,x和y将发生。当我们 在API中发布一个虚拟方法,我们 你打电话的时候不仅要保证 这个方法,x和y将会发生。我们 也要保证当你超越 这个方法,我们将在这里调用它 关于 这些其他人和国家将 在这个和那个不变量中

每次你在API中说虚拟, 您正在创建回调挂钩。作为 操作系统或API框架设计器, 你必须非常小心 那个您不希望用户覆盖 并在任意一点上钩 API,因为您不必 做出那些承诺。人们可能会 不完全理解他们的承诺 当他们做东西的时候,他们在做什么 虚拟的


另请参见Anders Hejlsberg(C#的发明者)的答案。

换言之,设计C#的人之一: 因此,当您从第三方收到的源代码发生更改时,您的代码不会意外损坏。换言之,是为了防止这种情况


如果一个方法是虚拟的,如果是因为你(假设)做出了有意识的决定,允许该功能是可替换的,并围绕该功能进行了设计、测试和记录。如果,比方说,您创建了一个函数“frob”,并且在随后的一些版本中,基类的创建者决定也创建一个函数“frob”,会发生什么情况呢?

当您想要指定允许或拒绝某些内容时,通常有两种方法。你可以信任每一个人,惩罚罪人,也可以不信任每一个人,强迫他们请求允许

虚拟方法存在一些较小的性能问题,不能内联,调用速度比非虚拟方法慢,但这并不重要

更重要的是,它们构成了威胁