非虚拟接口(NVI)习惯用法在C#中是否像在C++中一样有用?

7
在C++中,我经常需要使用NVI来确保我的API的一致性。虽然我在C#中看不到它被广泛使用,但我想知道这是因为C#作为一种语言提供了使NVI变得不必要的功能吗?(在需要时,我仍然会在C#中使用NVI。)

哪些C#特性使其不必要的兴趣? - user243357
嗯,这就是我想知道的,因为我自己看不到它们 - 我使用NVI。 :) - Johann Gerell
4个回答

8
C#在NVIs方面存在问题,因为它取消了多继承。虽然我认为多重继承产生的负面效应大于正面效应,但在大多数情况下,它对于NVI是必要的。最简单的解决方法是:在C#中,一个类不能实现多个NVI。一旦发现了C# / NVI组合的这个令人不快的方面,放弃NVI比放弃C#容易得多。
顺便说一下,谈到方面。这是一个非常有趣的概念,其目的与NVI完全相同,只是它试图从“真正的本质”角度来看待问题并“适当地”解决它。看一下
至于.NET Framework,有一种机制可以做到这一点:注入与主要逻辑“正交”的代码。我说的是所有MarshalByRef/TransparentProxy业务,我相信你也听说过。它确实会严重影响性能,所以运气不太好。
还有许多尝试通过其他技术实现相同概念的企图,从构建门面到上述肮脏的业务再到MSIL的后处理。
后一种方法恰好最吸引我的一点,因为它可以被透明地制作(通过将所需步骤合并到构建例程中),它不会影响性能(比实际执行“正交”代码所必需的更多),也不涉及某种“黑客”或反向工程,因为MSIL是开放且有很好的文档记录。 这里可以找到更详细地讨论这些要点的信息,以及更多信息和实际工具的链接。使用谷歌进行同样的目的也是可以接受的。祝你好运。

警告,PostSharp 可能会让你上瘾。 ;p - Steven Jeuris

5
我认为解释很简单,因为在C#中,“传统”的Java风格的面向对象编程更加深入人心,而NVI与之相反。C#有一个真正的interface类型,而NVI则依赖于“interface”实际上是一个基类。无论如何,在C++中都是这样做的,所以它自然适合在那里使用。
在C#中,仍然可以这样做,而且这仍然是一个非常有用的习惯用法(我认为比“普通”接口更有用),但是它要求您忽略内置语言功能。
许多C#程序员不会认为NVI类是“适当的接口”。我认为这种心理抵抗是它在C#中较少使用的唯一原因。

4

Trey Nash在他的书Accelerated C#中,推广NVI模式作为C#中的规范形式。

我不知道你所引用的文章(More C++ Idioms/Non-Virtual Interface)是谁写的,但我觉得作者没有抓住重点。

...

接口与抽象类

我认为,在C#中,从哲学上讲,完全抽象的类(即没有任何实现)与接口之间几乎没有区别。表面上,它们都可以提供可执行的方法签名,并要求其他东西来实现该功能。

在C#中,如果您需要一个接口,则始终应编写一个接口。只有在您还想要实现重用时,才使用(抽象)基类。

许多代码库将这些组合在一起,并在提供类层次结构作为接口的默认实现的同时编写接口。

C中接口的NVI

如果您在C ++中使用NVI的唯一动机是拥有接口,则不,您不会在C#中使用此功能,因为语言/CLR提供了接口作为一流特性。

NVI和对象层次结构

在我看来,NVI从来都不是关于接口。它总是实现模板方法模式的一种绝佳方式。

其有用之处体现在代码生命周期维护(易于更改、扩展等)方面,并提供了更简单的继承模型。

我的意见:是的,在C#中,NVI非常有用。


0

我认为在C#中,NVI和在C++中一样有用。我经常在我的公司看到它被广泛使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接