为什么在内部类中使用公共方法?

在我们的一个项目中,有很多代码看起来像这样:

internal static class Extensions
{
public static string AddFoo(this string s)
{
if (s == null)
{
return "Foo";
}


return $({s}Foo);
}
}

除了“以后更容易将类型公开”之外,还有其他明确的原因吗?

我怀疑它只在非常奇怪的边缘情况下(在Silverlight反射)或根本不重要。

50168 次浏览

internal表示只能从同一个程序集中访问成员。该程序集中的其他类可以访问internal public成员,但不能访问privateprotected成员,无论是否为internal

我怀疑“以后公开类型会更容易吗?”

作用域规则意味着方法只能显示为internal——因此方法是否标记为publicinternal并不重要。

我想到的一种可能是,类是public的,后来被改为internal,开发人员没有费心去更改所有的方法可访问性修饰符。

它是一样的,public方法将被标记为内部的,因为它在内部类中,但它有一个优点(正如你所说),如果你想将类标记为公共的,你必须修改更少的代码。

我经常在内部类中将我的方法标记为public而不是internal: a)这并不重要;b)我使用internal来表明该方法是故意内部的(我不想在公共类中公开此方法是有原因的。因此,如果我有一个内部方法,在把它改为公共方法之前,我真的必须理解为什么它是内部的,而如果我在内部类中处理一个公共方法,我真的必须考虑为什么这个类是内部的,而不是为什么每个方法是内部的。

如果类是internal,从可访问性的角度来看,将方法标记为internal还是public并不重要。但是,如果类是public,则使用您将使用的类型仍然很好。

虽然有些人说这简化了从internalpublic的转换。它也作为方法描述的一部分。Internal方法对于不受约束的访问通常被认为是不安全的,而public方法被认为是(大部分)自由游戏。

通过像在public类中那样使用internalpublic,可以确保传达预期的访问风格,同时也简化了将来使类public所需的工作。

在某些情况下,也可能是内部类型实现了一个公共接口,这意味着在该接口上定义的任何方法仍然需要声明为公共。

更新:这个问题是2014年9月我博客的主题。谢谢你的好问题!

甚至在编译器团队内部也存在相当大的争论。

首先,明智的做法是了解规则。类或结构的公共成员是可访问的可以访问包含类型的任何对象成员。因此内部类的公共成员实际上是内部的。

那么现在,给定一个内部类,您希望在程序集中访问的它的成员应该被标记为public还是internal呢?

我的意见是:把这样的成员标记为公共的。

我用“public”来表示“这个成员不是一个实现细节”。受保护成员是一个实现细节;有一些关于它的东西将需要使一个派生类工作。内部成员是一个实现细节;此程序集的其他内部程序需要该成员才能正确工作。公共成员表示“此成员表示此对象提供的键、文档化功能”。

基本上,我的态度是:假设我决定把这个内部类变成一个公共类。为了做到这一点,我想改变只有一件事:类的可访问性。如果将一个内部类转换为公共类意味着我必须将一个内部成员转换为公共成员,那么该成员是类的公共面积的一部分,并且它首先应该是公共的。

其他人不同意。有一种情况说,他们希望能够一眼看到成员的声明,并立即知道它是否只会从内部代码调用。

不幸的是,这并不总是很好;例如,实现内部接口的内部类仍然必须将实现成员标记为public,因为它们是类的公共表面的一部分. dll是它们是类的公共表面的一部分. dll。

我今天真的很纠结这个问题。到目前为止,如果类是internal,我会说方法都应该用internal标记,并且会认为其他任何东西都只是糟糕的编码或懒惰,特别是在企业开发中;然而,我必须子类化一个public类并重写它的一个方法:

internal class SslStreamEx : System.Net.Security.SslStream
{
public override void Close()
{
try
{
// Send close_notify manually
}
finally
{
base.Close();
}
}
}

方法必须是public,这让我想到,将方法设置为internal真的没有逻辑意义,除非它们真的必须是,正如Eric Lippert所说。

直到现在,我从来没有真正停下来思考过这个问题,我只是接受了它,但在阅读了Eric的帖子后,它真的让我思考,经过很多深思熟虑后,它有很多意义。

这确实有区别。 在我们的项目中,我们已经做了很多内部类,但是我们在另一个程序集中做单元测试,在我们的程序集信息中,我们使用InternalsVisibleTo来允许UnitTest程序集调用内部类。 我注意到,如果内部类有一个内部构造函数,我们不能使用激活器创建实例。CreateInstance在单元测试程序集中。但如果我们将构造函数更改为public,但类仍然是内部的,它就可以正常工作。 但我想这是一个非常罕见的情况(就像Eric在最初的帖子中说的:反思)

我想我对此有另外的看法。起初,我想知道在内部类中将某些东西声明为public有什么意义。然后我在这里结束了,读到如果您稍后决定将类更改为public可能会很好。真实的。所以,在我的脑海中形成了一个模式: 如果它没有改变当前的行为,那么是允许的,并且允许在代码的当前状态下没有意义(并且没有伤害)的事情,但是如果您更改类的声明,它将会。

是这样的:

public sealed class MyCurrentlySealedClass
{
protected void MyCurretlyPrivateMethod()
{
}
}
根据我上面提到的“模式”,这应该是完全没问题的。它遵循同样的思想。它表现为private方法,因为你不能继承这个类。但如果你删除了sealed约束,它仍然有效:继承的类可以看到这个方法,这绝对是我想要实现的。但是你会得到一个警告:CS0628CA1047。它们都是关于不要在sealed类中声明protected成员。此外,我发现完全一致,关于这是毫无意义的:'密封类中的受保护成员'警告(单例类) < / > < / p >

因此,在这个警告和相关的讨论之后,我决定在一个内部类中使所有内容都变得内部或更少,因为它更符合那种思维方式,而且我们不会混合不同的“模式”。

出于与在任何其他类中使用公共方法相同的原因——因此它们对包含类型外部是公共的。

类型的访问修饰符与其成员的访问修饰符完全没有关系。这两个决定是完全独立的。

仅仅因为类型和成员的修饰语的某些组合产生了看似相同的结果(或者其他人称之为“有效”)并不意味着它们在语义上是相同的。

实体的本地访问修饰符(在代码中声明)和它的全局有效访问级别(通过包含链评估)也是完全不同的东西。一间上了锁的大楼里的开放式办公室仍然是开放的,即使你不能从街上真正进入它。

不要考虑最终结果。首先,想想你在当地需要什么。

  • Public's Public:经典情况。
  • Public's Internal: type是public,但是你想在程序集中获得一些半合法的访问权限来做一些古怪的事情。
  • Internal's Public:你隐藏了整个类型,但在程序集中它有一个经典的公共表面
  • Internal's Internal:我想不出任何现实世界的例子。也许很快就会成为公众的内部信息?

Internal's Public vs Internal's Internal是一个错误的困境。这两个词的意思完全不同,应该在各自的情况下使用,不能重叠。