Friend 访问修饰符打算在哪里使用?

Posted

技术标签:

【中文标题】Friend 访问修饰符打算在哪里使用?【英文标题】:Where is the Friend access modifier intended to be used? 【发布时间】:2012-04-06 03:29:39 【问题描述】:

我唯一看到使用 Friend 修饰符的地方是在 WinForms 设计器中,正如在 Why is the modifier set to Friend in Winforms? 和 VB.NET: what does the 'friend' modifier do? 中提到的那样。

Friend 修饰符似乎是一个几乎任意宽的访问级别,它是为了解决 VB 中的一些历史性架构问题而创建的,我只是想知道是否有人对它有有意义的持续使用?

我有一些愿望,只将方法公开给给定的命名空间,以便将相关对象集合的功能组合在一起并管理它们的任何非线程安全方法,同时将安全的公共方法公开给更广泛的范围在同一个程序集中。 Friend 尚不存在此访问级别。那么可能是一个必然的问题,我对程序集和命名空间的使用是否与预期不一致?

在许多情况下,由于程序集具有严格的层次结构,因此不可能将功能分离到不同的程序集中,这导致一组相关但独立的对象可以访问彼此的不安全方法。

编辑: 虽然我知道修饰符的功能,但我很好奇人们对它有什么实际目的,因为我还没有遇到过它是正确解决方案的情况。

【问题讨论】:

【参考方案1】:

我在类中使用它来防止函数、方法或属性在我的程序集之外被使用。

在程序集中,FriendPublic 做同样的事情,因此,它对开发人员友好。但是,如果从外部程序集中使用该类,则标记为 Friend 的所有内容都将不可用,而 Public 将可用。

C# 等效项是internal。名称 internal 可能比 Friend 更准确地定义了它的预期用途。

这是一个任意的例子。我有一个 DLL,其中包含一堆自定义控件,这些控件都需要绘制某些图像:

Friend Class ControlDraw

  Public Shared Sub DrawArrow(ByVal g As Graphics, ByVal r as Rectangle, _
                              ByVal ad As ArrowDirection, ByVal ac As Color)

    //' Draw Special Arrow:

  End Sub

End Class

我可以在项目中的所有控件中使用此代码。但是当我发布 DLL 并让其他人使用它时,最终用户无法使用 DrawArrow 函数,只有项目内部的控件。

为什么要这样做?

如果是Public,那么我永远无法更改参数而不会破坏函数的任何使用者。但由于这是我自己的方法,我可以为 BackColor 或其他任何参数添加另一个参数,并从我自己的项目中更新所有使用它的控件。

我基本上是说,Friend 类或函数只是让我担心,而不是最终用户。一旦你向外界做出了Public 的东西,你就会失去一点控制权。

还从Eric Lippert answer on using Internal 中找到了这个:

内部的意义并不是让 Bob 过不下去。正是因为它允许您控制项目 A 在功能、生命周期、兼容性等方面做出的昂贵承诺。

【讨论】:

感谢 Lars,虽然我很清楚修饰符的作用,但我更感兴趣的是它为什么存在。它的范围看起来任意宽,并且类似(即命名空间)范围也不包括在规范中。事后看来,标题问题可能会稍微误导我的意图。 @JCollins 添加了一个示例。希望它有所帮助。 当你有一个商业的.dll时它非常有用。如果您出售(例如)您构建的一堆控件。也许有些类或函数是你想要公开的,但只是为了你的需要,也许这些函数不应该被其他人调用,因为如果使用不正确可能会导致系统崩溃。【参考方案2】:

你所拥有的不是语言问题,而是一般的 OOP 教条。

Friend 修饰符可能会令人困惑,因为它的行为方式与 C++ 等旧语言不同。它的行为方式不一样的原因是因为不一样。

Friend 修饰符允许访问程序集范围内声明的对象,这意味着程序集中的任何类都可以访问该对象,但它仍然不能用于使用程序集的代码。如果有帮助,请查看 C# Internal Modifier。

至于为什么 OOP 与 Friend Modifier 的 C++ 方式背道而驰,这超出了我的知识范围,但也许 this other SO question 可能会有所帮助。

【讨论】:

Pedro 谢谢你,C++ 定义正是我正在寻找的功能。我和你一样质疑为什么 .net 语言会省略它。 我认为它本身不是 .NET...如果我错了,请有人纠正我,但 Java 或任何其他 OOP 语言都没有提供作为 C++ Friend 修饰符的功能。另一方面,您的所有程序集都可以访问您的 Friend 成员是有道理的,我的意思是,您不应该四处不信任自己或您的团队。 如果我们想讨论语言之间“朋友”使用的差异,我们应该重新标记问题以包括“C++”。不确定这是 OP 真正想要的还是仅限于 .Net 宇宙的“为什么”。

以上是关于Friend 访问修饰符打算在哪里使用?的主要内容,如果未能解决你的问题,请参考以下文章

java中哪个修饰符可以使在一个类中定义的成员变量只能被同一包中的类访问?

访问修饰符

访问修饰符与可选修饰符static的使用

java 访问修饰符

修饰符

Java中各种(类方法属性)访问修饰符与修饰符的说明