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

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

        return $({s}Foo);
    }
}

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

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


当前回答

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

其他回答

Internal表示只能从同一程序集中访问成员。该程序集中的其他类可以访问内部公共成员,但不能访问私有成员或受保护成员(无论是否是内部成员)。

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

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

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

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

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

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

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

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

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

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

作用域规则意味着该方法只能作为内部方法可见——因此将方法标记为公共方法还是内部方法并不重要。

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

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

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

方法必须是公共的,这让我想到,将方法设置为内部没有逻辑意义,除非它们真的必须是,就像Eric Lippert说的那样。

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

I think I have an additional opinion on this. At first, I was wondering about how it makes sense to declare something to public in an internal class. Then I have ended up here, reading that it could be good if you later decide to change the class to public. True. So, a pattern formed in my mind: If it does not change the current behavior, then be permissive, and allow things that does not makes sense (and does not hurt) in the current state of code, but later it would, if you change the declaration of the class.

是这样的:

public sealed class MyCurrentlySealedClass
{
    protected void MyCurretlyPrivateMethod()
    {
    }
}

According to the "pattern" I have mentioned above, this should be perfectly fine. It follows the same idea. It behaves as a private method, since you can not inherit the class. But if you delete the sealed constraint, it is still valid: the inherited classes can see this method, which is absolutely what I wanted to achieve. But you get a warning: CS0628, or CA1047. Both of them is about do not declare protected members in a sealed class. Moreover, I have found full agreement, about that it is senseless: 'Protected member in sealed class' warning (a singleton class)

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