c++的friend关键字允许类a将类B指定为它的friend。这允许类B访问类A的私有/受保护成员。

我从来没有读过任何关于为什么c#(和VB.NET)中不包含这个的东西。大多数关于StackOverflow问题的答案似乎都在说它是c++的一个有用的部分,并且有很好的理由使用它。以我的经验,我不得不同意。

对我来说,另一个问题似乎是在问如何在c#应用程序中做类似于friend的事情。虽然答案通常围绕嵌套类,但它似乎没有使用friend关键字那么优雅。

最初的《设计模式》一书在其示例中经常使用它。

总之,为什么在c#中没有friend,在c#中模拟friend的“最佳实践”方法是什么?

(顺便说一下,internal关键字不是一回事,它允许整个程序集中的所有类访问内部成员,而friend允许你给某个类完全访问另一个类)


当前回答

从。net 3开始就有了InternalsVisibleToAttribute,但我怀疑他们只是在单元测试兴起后才添加它来迎合测试程序集。我想不出还有什么其他理由来使用它。

它在组装层工作但它能完成内部不能完成的工作;也就是说,您希望分发一个程序集,但希望另一个非分布式程序集具有对该程序集的特权访问。

很正确地,他们要求好友程序集是强键的,以避免有人在你受保护的程序集旁边创建一个假装的好友。

其他回答

您可以保持它为私有,并使用反射来调用函数。测试框架可以做到这一点,如果你要求它测试一个私有函数

拥有编程领域的朋友或多或少被认为是“肮脏的”,容易被滥用。它破坏了类之间的关系,破坏了OO语言的一些基本属性。

也就是说,这是一个很好的特性,我自己在c++中使用过很多次;并且也想在c#中使用它。但我敢打赌,因为c#的“纯”OOness(与c++的伪OOness相比),MS决定因为Java没有朋友,关键字c#也不应该(开玩笑;))

严肃地说:内部关系不如朋友关系好,但它确实能完成工作。请记住,您很少会不通过DLL将代码分发给第三方开发人员;因此,只要您和您的团队了解内部类及其使用,就应该没问题。

让我来澄清一下friend关键字是如何破坏OOP的。

私有和受保护的变量和方法可能是OOP中最重要的部分之一。对象可以保存只有它们可以使用的数据或逻辑的思想允许您编写独立于环境的功能实现—并且您的环境不能更改它不适合处理的状态信息。通过使用friend,你将两个类的实现耦合在一起——这比仅仅耦合它们的接口要糟糕得多。

你可以用c#关键字“internal”来接近c++的“朋友”。

如果有朋友,c++设计人员可以精确控制私有*成员暴露给谁。但是,他被迫暴露了每一个私人成员。

对于内部,c#设计器可以精确控制他所公开的私有成员集。显然,他只能暴露单个私有成员。但是,它将暴露给程序集中的所有类。

通常,设计人员只希望将少数私有方法暴露给选定的少数其他类。例如,在类工厂模式中,可能希望类C1只由类工厂CF1实例化。因此类C1可能有一个受保护的构造函数和一个友类工厂CF1。

As you can see, we have 2 dimensions along which encapsulation can be breached. friend breaches it along one dimension, internal does it along the other. Which one is a worse breach in the encapsulation concept? Hard to say. But it would be nice to have both friend and internal available. Furthermore, a good addition to these two would be the 3rd type of keyword, which would be used on member-by-member basis (like internal) and specifies the target class (like friend). * For brevity I will use "private" instead of "private and/or protected". - Nick

顺便说一句。 使用friend并不是违反封装,相反,它是加强封装。就像访问器+突变器、操作符重载、公共继承、向下强制转换等一样,它经常被误用,但这并不意味着关键字没有,或者更糟,没有一个坏的目的。

请参阅Konrad Rudolph在另一个线程中的消息,或者如果您愿意,请参阅c++常见问题解答中的相关条目。