6

我知道标题可能不完全清楚,但我不想让它太长。

在考虑对部分方法施加的限制时,有一件事让我感到困惑。在我看来,规则是不一致的。你可能知道:

部分方法的返回类型必须始终为 void,并且它们不能有任何用 out 修饰符标记的参数。这些限制是存在的,因为在运行时,该方法可能不存在,因此您无法将变量初始化为该方法可能返回的值,因为该方法可能不存在。同样,您不能有 out 参数,因为该方法必须对其进行初始化,并且该方法可能不存在。[1]

这对我来说听起来很明智。但同时:

如果没有实现分部方法声明,那么您不能有任何代码尝试创建引用分部方法的委托。同样,原因是该方法在运行时不存在。[1]

起初,所有这些规则似乎都遵循相同的编译器逻辑。不过还是有区别的。如第二个引用所述,编译器仅在部分方法没有方法实现时才会发出错误。为什么它不能在其他情况下在编译时检查实现?这将在使用部分方法时提供更大的灵活性,并且所有规则背后的逻辑都是相同的。

恐怕我能得到的唯一答案是“因为它是这样实现的”,但也许还有更多的东西?

[1] CLR 通过 C#,第四版

4

2 回答 2

2

部分方法的重点是在生成的代码场景中促进可扩展性,而不会影响运行时性能。代码生成器发出部分方法签名,然后发出调用此部分方法的代码。

现在,在编译时,如果没有实现该方法,这些调用站点将被完全删除,剩余的代码必须是有效的。引号在这方面令人困惑,因为它们谈论的是方法的“运行时存在”。这是胡说八道:一切都在编译时解决。

这就是差异的原因:您首先引用的规则对方法签名施加了限制,而委托规则对方法使用施加了限制。

有关签名的规则确保您可以以某种方式调用方法,如果方法调用被删除,代码将保持有效。部分方法的预期用例是它们99% 的时间都不存在。如果您需要实现它们,那么这不是您应该首先使用的功能。使用抽象方法或类似方法。

为方法构建委托就像获取方法的指针一样,如果方法不存在,则不能这样做(好吧,我想您可能会争辩说编译器此时可以只替换委托null,但是你不能写,比如说,new Action(null)),但如果该方法确实存在,为了实施者的方便,没有理由禁止它。但是代码生成器不应该发出为方法创建委托的代码。

于 2015-06-10T19:23:59.317 回答
1

请记住,部分方法的原因是它们可以在设计人员生成的代码中使用,即设计人员可以生成对方法的调用并将其(可选)实现留给人类开发人员(他们稍后将编译代码)。如果按照您的建议,在未实现该方法时调用给出了编译时错误,那么在某些情况下生成的代码将无法编译,直到开发人员更改生成的代码(通常是一个坏主意)或直到他实现了所有方法。

C# 已经有接口和抽象方法来强制方法实现,部分方法尝试做其他事情。

于 2015-06-10T22:02:40.103 回答