在我们的一个项目中,有很多代码看起来像这样:
internal static class Extensions
{
public static string AddFoo(this string s)
{
if (s == null)
{
return "Foo";
}
return $({s}Foo);
}
}
除了“以后更容易将类型公开”之外,还有其他明确的原因吗?
我怀疑它只在非常奇怪的边缘情况下(在Silverlight反射)或根本不重要。
更新:这个问题是我2014年9月博客的主题。谢谢你的好问题!
甚至在编译器团队内部也存在相当大的争论。
首先,明智的做法是了解规则。类或结构的公共成员是可以被任何可以访问包含类型的对象访问的成员。因此内部类的公共成员实际上是内部的。
那么现在,给定一个内部类,您希望在程序集中访问的它的成员应该被标记为public还是internal呢?
我的意见是:把这样的成员标记为公共的。
我用“public”来表示“这个成员不是一个实现细节”。受保护成员是一个实现细节;有一些关于它的东西将需要使一个派生类工作。内部成员是一个实现细节;此程序集的其他内部程序需要该成员才能正确工作。公共成员表示“此成员表示此对象提供的键、文档化功能”。
基本上,我的态度是:假设我决定把这个内部类变成一个公共类。为了做到这一点,我只想改变一件事:类的可访问性。如果将一个内部类转换为公共类意味着我还必须将一个内部成员转换为公共成员,那么该成员是类的公共表面积的一部分,并且它首先就应该是公共的。
其他人不同意。有一种情况说,他们希望能够一眼看到成员的声明,并立即知道它是否只会从内部代码调用。
不幸的是,这并不总是很好;例如,实现内部接口的内部类仍然必须将实现成员标记为public,因为它们是类的公共表面的一部分。
出于与在任何其他类中使用公共方法相同的原因——因此它们对包含类型外部是公共的。
类型的访问修饰符与其成员的访问修饰符完全没有关系。这两个决定是完全独立的。
仅仅因为类型和成员的修饰符的某些组合产生了看似相同的结果(或者其他人称之为“有效”)并不意味着它们在语义上是相同的。
实体的本地访问修饰符(在代码中声明)和它的全局有效访问级别(通过包含链评估)也是完全不同的东西。一间上了锁的大楼里的开放式办公室仍然是开放的,即使你不能从街上真正进入它。
不要考虑最终结果。首先,想想你在当地需要什么。
公众的公众:经典的情况。
Public的Internal:类型是Public,但是你想在程序集中获得一些半合法的访问权限来做一些古怪的事情。
内部的公共:你隐藏了整个类型,但在程序集中它有一个经典的公共表面
内部的内部:我想不出任何现实世界的例子。也许很快就会成为公众的内部信息?
内部的公众vs内部的内部是一个虚假的困境。这两个词的意思完全不同,应该在各自的情况下使用,不能重叠。
更新:这个问题是我2014年9月博客的主题。谢谢你的好问题!
甚至在编译器团队内部也存在相当大的争论。
首先,明智的做法是了解规则。类或结构的公共成员是可以被任何可以访问包含类型的对象访问的成员。因此内部类的公共成员实际上是内部的。
那么现在,给定一个内部类,您希望在程序集中访问的它的成员应该被标记为public还是internal呢?
我的意见是:把这样的成员标记为公共的。
我用“public”来表示“这个成员不是一个实现细节”。受保护成员是一个实现细节;有一些关于它的东西将需要使一个派生类工作。内部成员是一个实现细节;此程序集的其他内部程序需要该成员才能正确工作。公共成员表示“此成员表示此对象提供的键、文档化功能”。
基本上,我的态度是:假设我决定把这个内部类变成一个公共类。为了做到这一点,我只想改变一件事:类的可访问性。如果将一个内部类转换为公共类意味着我还必须将一个内部成员转换为公共成员,那么该成员是类的公共表面积的一部分,并且它首先就应该是公共的。
其他人不同意。有一种情况说,他们希望能够一眼看到成员的声明,并立即知道它是否只会从内部代码调用。
不幸的是,这并不总是很好;例如,实现内部接口的内部类仍然必须将实现成员标记为public,因为它们是类的公共表面的一部分。