我们的一个项目中有很多代码如下:
internal static class Extensions
{
public static string AddFoo(this string s)
{
if (!string.IsNullOrEmpty(s)) return s + "Foo";
return "Foo";
}
}
有没有明确的理由去做“除了以后更容易公开这种类型?”
我怀疑它只适用于非常奇怪的边缘情况(Silverlight中的反射)或根本不存在。
答案 0 :(得分:363)
更新:这个问题是the subject of my blog in September 2014。谢谢你提出的好问题!
即使在编译器团队本身内,对这个问题也存在相当大的争议。
首先,了解规则是明智的。类或结构的公共成员是可以访问的任何可以访问包含类型的成员。因此,内部类的公共成员实际上是内部成员。
现在,鉴于内部类,您希望在程序集中访问的成员是否应标记为公共或内部?
我的意见是:将此类成员标记为公开。
我使用“public”来表示“此成员不是实现细节”。受保护的成员是实现细节;有一些东西需要它来使派生类工作。内部成员是实现细节;此程序集内部的其他内容需要该成员才能正常工作。公共成员说“此成员代表此对象提供的关键,记录的功能。”
基本上,我的态度是:假设我决定将这个内部课程变成公共课程。为了做到这一点,我想改变完全一件事:类的可访问性。如果将内部类转换为公共类意味着我还必须将内部成员转换为公共成员,那么该成员是该类的公共表面区域的一部分,它应该是公众首先。
其他人不同意。有一个特遣队说,他们希望能够看一眼成员的声明,并立即知道是否只能从内部代码调用它。
不幸的是,这并不总能很好地解决;例如,实现内部接口的内部类仍然必须将实现成员标记为public,因为它们是类的公共表面的一部分。
答案 1 :(得分:14)
如果课程为internal
,则从辅助功能的角度来看,无论您是标记方法internal
还是public
,都无关紧要。但是,如果类为public
,则使用您将使用的类型仍然很好。
虽然有些人说这可以简化从internal
到public
的过渡。它也是该方法描述的一部分。 Internal
方法通常被认为对于不受限制的访问不安全,而public
方法被认为是(大部分)免费游戏。
使用internal
或public
,就像在public
课程中一样,确保您正在传达预期的访问方式,同时还可以简化制作将来会成为public
。
答案 2 :(得分:10)
我经常在内部类中标记我的方法而不是内部类,因为a)它并不重要; b)我使用internal指示方法是内部故意的(有一些原因我不想要在公共类中公开这个方法。因此,如果我有一个内部方法,我真的必须在将其更改为public之前理解它的内部原因,而如果我在内部类中处理公共方法,我真的要思考关于为什么这个类是内部的,而不是为什么每个方法都是内部的。
答案 3 :(得分:8)
我怀疑"以后更容易公开这种类型?"是吗。
范围规则意味着该方法仅作为internal
显示 - 因此方法是否标记为public
或internal
并不重要。
我想到的一种可能性是,类是公开的,后来更改为internal
,开发人员也没有费心去更改所有方法可访问性修饰符。< / p>
答案 4 :(得分:7)
在某些情况下,也可能是内部类型实现了一个公共接口,这意味着在该接口上定义的任何方法仍然需要声明为public。
答案 5 :(得分:2)
同样,公共方法将被标记为内部,因为它在内部类中,但它有一个优点(如您所知),如果您想将该类标记为公共,则必须更改更少的代码
答案 6 :(得分:0)
internal
表示只能在同一个程序集中访问该成员。该程序集中的其他类可以访问internal public
成员,但无法访问private
或protected
成员,internal
。
答案 7 :(得分:0)
我今天真的很挣扎。到目前为止,我会说如果类是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的帖子后,它确实让我思考,经过大量的商议后它很有意义。
答案 8 :(得分:0)
确实存在差异。 在我们的项目中,我们已经在内部创建了很多类,但是我们在另一个程序集中进行单元测试,在我们的汇编信息中,我们使用InternalsVisibleTo来允许UnitTest程序集调用内部类。 我注意到如果内部类有一个内部构造函数,我们由于某种原因无法在单元测试程序集中使用Activator.CreateInstance创建实例。但是如果我们将构造函数更改为public但类仍然是内部的,那么它可以正常工作。 但我想这是一个非常罕见的案例(就像埃里克在原帖中所说:反思)。
答案 9 :(得分:0)
我想我对此有另外的意见。起初,我想知道在内部课堂中向公众宣布某些内容是否合理。然后我结束了这里,读到如果你以后决定将课程改为公开,那可能会很好。真正。所以,在我的脑海中形成了一个模式:如果它不改变当前的行为,那么是宽容的,并允许在当前状态下没有意义(并且没有伤害)的事情代码,但稍后如果你改变了类的声明,它会。
像这样:
public sealed class MyCurrentlySealedClass
{
protected void MyCurretlyPrivateMethod()
{
}
}
根据我上面提到的“模式”,这应该是完全没问题的。它遵循相同的想法。它表现为private
方法,因为您无法继承该类。但是如果删除sealed
约束,它仍然有效:继承的类可以看到这个方法,这绝对是我想要实现的。但是您会收到警告:CS0628
或CA1047
。它们都是关于不在protected
类中声明sealed
成员。此外,我已经完全同意,这是毫无意义的:'Protected member in sealed class' warning (a singleton class)
所以在这个警告和讨论相关联之后,我决定在内部课堂上制作内部或更少内容,因为它更符合这种思维,我们不会混合不同的“模式”。