在 C++ 中,我经常需要NVI来获得 API 的一致性。不过,我认为它在 C# 中的使用并不多。我想知道这是否是因为 C# 作为一门语言提供了不需要 NVI 的功能?(不过,在需要的地方,我仍然在 C# 中使用 NVI。)
4 回答
C# 通过取消多重继承给 NVI 带来了问题。虽然我确实认为多重继承产生的恶多于善,但它(在大多数情况下)对于 NVI 来说是必要的。想到的最简单的事情是:C# 中的一个类不能实现多个 NVI。一旦发现 C#/NVI 串联的这个令人不快的方面,放弃 NVI 就比 C# 容易得多。
顺便说一下,谈到方面。这是一个非常有趣的概念,它的目标与 NVI 的目标完全相同,只是它试图看到问题的“本质”并“正确”解决它,可以这么说。看一看。
就 .NET Framework 而言,有一种机制可以做到这一点:将“正交”代码注入手头的主要逻辑。我说的是 MarshalByRef/TransparentProxy 的所有业务,我相信你已经听说过。但是,它确实会严重影响性能,所以这里没有太大的运气。
也有许多尝试通过其他技术来实现相同的概念,从建筑立面到上面提到的肮脏业务再到 MSIL 的后处理。
后一种方法恰好最能吸引您,因为它可以变得透明(通过将所需的步骤合并到一个构建例程中),它不会影响性能(超过实际执行“正交”代码所绝对必要的)它不涉及某种“黑客”或逆向工程,因为 MSIL 是开放的并且有据可查。
在这里可以找到更详细讨论的这些要点,以及更多信息和实际工具的链接。出于相同目的使用 Google 也是可以接受的。:-)
祝你好运。
我认为解释很简单,在 C# 中,“传统”Java 风格的 OOP 更加根深蒂固,而 NVI 与此背道而驰。C# 有一个真正的interface
类型,而 NVI 依赖于实际上是一个基类的“接口”。无论如何,这就是它在 C++ 中的完成方式,因此它很自然地适合那里。
在 C# 中,它仍然可以完成,它仍然是一个非常有用的习惯用法(我想说,比“普通”接口更有用),但它要求您忽略内置的语言功能。
许多 C# 程序员只是不认为 NVI 类是“适当的接口”。我认为这种心理阻力是它在 C# 中不太常见的唯一原因。
Trey Nash在他的Accelerated C#一书中将 NVI 模式提升为 C# 中的规范形式。
我不知道你参考的文章是谁写的(More C++ Idioms/Non-Virtual Interface),但我觉得作者没有抓住重点。
...
接口与抽象类
我认为,从哲学上讲,完全抽象的类(即没有任何实现)与接口之间几乎没有区别(在 C# 中)。从表面上看,它们都可以提供可以执行的方法的签名,并且需要其他东西来实现该功能。
如果您需要的是接口,则使用 C# 总是会编程到接口。您只使用(抽象)基类,因为您还希望实现重用。
除了提供类层次结构作为接口的默认实现之外,许多代码库将这些和程序结合到接口中。
C 中接口的 NVI
如果您在 C++ 中使用 NVI 的唯一动机是拥有一个接口,那么不,您不会在 C# 中使用它,因为语言 / CLR 将接口作为一流的特性提供。
NVI 和对象层次结构
在我看来,NVI 从来就不是关于接口的。它一直是实现模板方法模式的绝佳方式。
有用性体现在代码生命周期维护(易于更改、扩展等)中,并提供了更简单的继承模型。
我的意见:是的,NVI 在 C# 中非常有用。
我认为 NVI 在 C# 中和在 C++ 中一样有用。我看到它在我的公司经常使用。