非虚拟接口 (NVI) 习惯用法在 C# 中和在 C++ 中一样有用吗?
在 C++ 中,我经常需要 NVI 来获得我的一致性蜜蜂。不过,我认为它在 C# 中的使用并不多。我想知道这是否是因为 C# 作为一种语言提供了不需要 NVI 的功能? (不过,如果需要的话,我仍然在 C# 中使用 NVI。)
In C++, I often needed NVI to get consistency in my APIs. I don't see it used as much among others in C#, though. I wonder if that is because C#, as a language, offers features that makes NVI unnecessary? (I still use NVI in C#, though, where needed.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C# 通过取消多重继承而给 NVI 带来了问题。虽然我确实认为多重继承弊大于利,但它对于 NVI 来说是必要的(在大多数情况下)。我想到的最简单的事情是:C# 中的一个类不能实现多个 NVI。一旦发现 C#/NVI 串联的这一令人不快的方面,放弃 NVI 就变得比放弃 C# 容易得多。
顺便说一下方面。这是一个非常有趣的概念,它的目标与 NVI 的目标完全相同,只是它试图看到问题的“真正本质”并“正确地”解决它,可以这么说。 看一下。
就 .NET Framework 而言,有一种机制可以做到这一点:可以说,注入“正交”的代码到手头的主要逻辑。我正在谈论所有 MarshalByRef/TransparentProxy 业务,我相信您已经听说过它。不过,它确实会严重影响性能,所以这里运气不佳。
人们还多次尝试通过其他技术来实现相同的概念,从建筑立面到上面提到的肮脏业务,再到 MSIL 的后处理。
后一种方法恰好对您最有吸引力,因为它可以变得透明(通过将所需的步骤合并到构建例程中),它不会影响性能(超过实际执行“正交”代码绝对必要的性能)而且它不涉及某种“黑客”或逆向工程,因为 MSIL 是开放的且有详细记录。
在这里可以找到更详细讨论的这些要点,以及更多信息和实际工具的链接。使用 Google 来达到同样的目的也是可以接受的。 :-)
祝你好运。
C# poses a problem with NVIs by taking away multiple inheritance. While I do think that multiple inheritance generates more evil than good, it is necessary (in most cases) for NVI. The simplest thing that jumps to mind: a class in C# cannot implement more than one NVI. Once one discovers this unpleasant aspect of C#/NVI tandem, it becomes much easier to give up NVIs than C#.
And by the way, speaking about aspects. That's a very interesting concept, and it's aim is exactly the same as that of NVIs, only it attempts to look at the "true essense" of the issue and address it "properly", so to say. Take a look.
And as far as .NET Framework goes, there is a mechanism to do just that: inject code that is "orthogonal", so to say, to the main logic at hand. I'm talking about all that MarshalByRef/TransparentProxy business, I'm sure you've heard of it. It does seriously impact performance, though, so no big luck here.
There have also been numerous attempts to implement the same concept through other techniques, from building facades to the dirty business mentioned above to post-processing of MSIL.
The latter approach happens to appeal to yours truly the most, since it can be made transparent (by incorporating needed steps into one's build routine), it doesn't affect performance (more than is absolutely necessary to actually execute the "orthogonal" code) and it does not involve some kind of "hacking" or reverse engineering, since MSIL is open and well documented.
Here one can find these points discussed in more detail, as well as more information and links to actual tools. Using Google for the same purpose is also acceptable. :-)
Good luck.
我认为解释很简单,在 C# 中,“传统”Java 风格的 OOP 更加根深蒂固,而 NVI 与此背道而驰。 C# 有一个真正的
接口
类型,而 NVI 依赖的“接口”实际上是一个基类。无论如何,这就是 C++ 中的实现方式,因此它自然适合 C++。在 C# 中,它仍然可以完成,并且它仍然是一个非常有用的习惯用法(我想说,比“正常”接口更有用),但它要求您忽略内置的语言功能。
许多 C# 程序员并不认为 NVI 类是“正确的接口”。我认为这种心理抗拒是它在 C# 中不太常见的唯一原因。
I think the explanation is simply that in C#, "traditional" Java-style OOP is much more ingrained, and NVI runs counter to that. C# has a real
interface
type, whereas NVI relies on the "interface" actually being a base class. That's how it's done in C++ anyway, so it fits naturally there.In C#, it can still be done, and it is still a very useful idiom (far more so, I'd say, than "normal" interfaces), but it requires you to ignore a built-in language feature.
Many C# programmers just wouldn't think of a NVI class as being "a proper interface". I think this mental resistance is the only reason why it's less common in C#.
特雷·纳什在他的书中加速 C# 将 NVI 模式提升为 C# 中的规范形式。
我不知道您引用的文章是谁写的(更多 C++ 习语/非虚拟接口),但我觉得作者没有抓住重点。
...
接口与抽象类
我认为,从哲学上讲,完全抽象类(即没有任何实现)与接口之间几乎没有区别(在 C# 中)。从表面上看,它们都可以提供可以执行的方法的签名,并且需要其他东西来实现该功能。
使用 C#,如果您需要的是接口,那么您总是会针对接口进行编程。您只使用(抽象)基类,因为您还希望实现重用。
除了提供类层次结构作为接口的默认实现之外,许多代码库还将这些组合起来并对接口进行编程。
C 中接口的 NVI
如果您在 C++ 中使用 NVI 的唯一动机是拥有一个接口,那么不,您不会在 C# 中使用它,因为语言/CLR 提供接口作为一流功能。
NVI 和对象层次结构
在我看来,NVI 从来都不是关于接口的。它始终是实现模板方法模式的绝佳方法。
其用处体现在代码生命周期维护(易于更改、扩展等),并提供更简单的继承模型。
我的看法:是的,NVI在C#中非常有用。
Trey Nash in his book Accelerated C# promotes the NVI pattern as a canonical form in C#.
I don't know who wrote the article you reference (More C++ Idioms/Non-Virtual Interface), but I feel the author missed the point.
...
Interface vs Abstract classes
I'd argue that, philosophically, there's little difference (in C#) between a fully abstract class (ie no implementation whatsoever) versus an interface. On the surface, they both can provide a signature of methods that can be performed and require something else to implement that functionality.
With C# you would always program to an interface if what you need is an interface. You only use an (abstract) base class because you also want implementation reuse as well.
Many code bases combine these and program to the interface in addition to providing a class hierarchy as a default implementation for the interface.
NVI for Interfaces in C
If your only motivation to use NVI in C++ would be to have an interface, then no, you're not going to use this in C# because the language / CLR provides interfaces as a first-class feature.
NVI and object hierarchies
In my mind, NVI has never been about interfaces. It's always been an excellent way to implement the template method pattern.
The usefulness manifests itself in code lifecycle maintenance (ease of change, extension, etc), and provides a simpler model of inheritance.
My opinion: Yes, NVI is very useful in C#.
我认为 NVI 在 C# 中和在 C++ 中一样有用。我发现它在我的公司中使用得非常频繁。
I think NVI is as useful in C# as it is in C++. I see it used very frequently at my company.