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

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

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

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

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

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


当前回答

Friend在编写单元测试时非常有用。

虽然这是以稍微污染类声明为代价的,但它也是一个编译器强制的提醒,提醒您测试实际上可能关心类的内部状态。

A very useful and clean idiom I've found is when I have factory classes, making them friends of the items they create which have a protected constructor. More specifically, this was when I had a single factory responsible for creating matching rendering objects for report writer objects, rendering to a given environment. In this case you have a single point of knowledge about the relationship between the report-writer classes (things like picture blocks, layout bands, page headers etc.) and their matching rendering objects.

其他回答

通过使用c#中的接口,您应该能够完成在c++中使用“friend”的相同种类的事情。它要求您显式地定义在两个类之间传递的成员,这是额外的工作,但也可能使代码更容易理解。

如果有人有一个合理使用“朋友”的例子,不能用界面模拟,请分享!我想更好地理解c++和c#之间的区别。

不要再为这种限制找借口了。朋友是坏的,但内在是好的?它们是一样的东西,只是那个朋友让你更精确地控制谁可以访问谁不能访问。

这是强制封装范式吗?所以你必须写访问器方法,然后呢?你应该如何阻止所有人(除了类B的方法)调用这些方法?你不能,因为你也控制不了,因为你失去了“朋友”。

No programming language is perfect. C# is one of the best languages I've seen, but making silly excuses for missing features doesn't help anyone. In C++, I miss the easy event/delegate system, reflection (+automatic de/serialization) and foreach, but in C# I miss operator overloading (yeah, keep telling me that you didn't need it), default parameters, a const that cannot be circumvented, multiple inheritance (yeah, keep telling me that you didn't need it and interfaces were a sufficient replacement) and the ability to decide to delete an instance from memory (no, this is not horribly bad unless you are a tinkerer)

我以前经常使用friend,我不认为它违反了OOP,也不认为它有任何设计缺陷。在一些地方,它是用最少的代码达到正确目的的最有效的方法。

One concrete example is when creating interface assemblies that provide a communications interface to some other software. Generally there are a few heavyweight classes that handle the complexity of the protocol and peer peculiarities, and provide a relatively simple connect/read/write/forward/disconnect model involving passing messages and notifications between the client app and the assembly. Those messages / notifications need to be wrapped in classes. The attributes generally need to be manipulated by the protocol software as it is their creator, but a lot of stuff has to remain read-only to the outside world.

声明协议/“创建者”类对所有创建的类的亲密访问是违反OOP的,这是非常愚蠢的——创建者类不得不在上升的过程中对每一点数据进行修改。我发现最重要的是尽量减少“为了面向对象而面向对象”模型通常导致的所有多余的代码行。额外的意大利面只会产生更多的虫子。

人们知道您可以在属性、属性和方法级别应用内部关键字吗?它不仅仅用于顶级类声明(尽管大多数示例似乎都显示了这一点)。

如果你有一个使用friend关键字的c++类,并且想在一个c#类中模拟它: 1. 将c#类声明为public 2. 将c++中受保护的所有属性/属性/方法声明为c#内部的 3.为所有内部属性和属性的公共访问创建只读属性

我同意它并不完全等同于好友,单元测试是一个非常有价值的例子,说明了需要好友之类的东西(就像协议分析器日志代码一样)。然而,internal提供了您想要公开的类的公开,[InternalVisibleTo()]处理其余的—似乎它是专门为单元测试而生的。

至于朋友“更好,因为你可以显式地控制哪些类可以访问”——一堆可疑的邪恶类在同一个程序集中做什么呢?对程序集进行分区!

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

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

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

关于信息,. net中另一个相关但不完全相同的东西是[InternalsVisibleTo],它允许一个程序集指定另一个程序集(例如单元测试程序集),该程序集(有效地)具有对原始程序集中的类型/成员的“内部”访问。