C# 为什么在内部类中使用公共方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9302236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why use a public method in an internal class?
提问by bopapa_1979
There is a lot of code in one of our projects that looks like this:
我们的一个项目中有很多代码如下所示:
internal static class Extensions
{
public static string AddFoo(this string s)
{
if (s == null)
{
return "Foo";
}
return $({s}Foo);
}
}
Is there any explicit reason to do this other than "it is easier to make the type public later?"
除了“以后更容易公开类型”之外,是否有任何明确的理由这样做?
I suspect it only matters in very strange edge cases (reflection in Silverlight) or not at all.
我怀疑它只在非常奇怪的边缘情况下(Silverlight 中的反射)或根本不重要。
采纳答案by Eric Lippert
UPDATE: This question was the subject of my blog in September 2014. Thanks for the great question!
更新:这个问题是我 2014 年 9 月博客的主题。谢谢你的好问题!
There is considerable debate on this question even within the compiler team itself.
即使在编译器团队内部,对这个问题也有相当多的争论。
First off, it's wise to understand the rules. A public member of a class or struct is a member that is accessible to anything that can access the containing type. So a public member of an internal class is effectively internal.
首先,了解规则是明智的。类或结构的公共成员是任何可以访问包含类型的成员都可以访问的成员。因此,内部类的公共成员实际上是内部类。
So now, given an internal class, should its members that you wish to access in the assembly be marked as public or internal?
那么现在,给定一个内部类,您希望在程序集中访问的它的成员应该标记为 public 还是 internal?
My opinion is: mark such members as public.
我的意见是:将此类成员标记为公开。
I use "public" to mean "this member is not an implementation detail". A protected member is an implementation detail; there is something about it that is going to be needed to make a derived class work. An internal member is an implementation detail; something else internal to this assembly needs the member in order to work correctly. A public member says "this member represents the key, documented functionality provided by this object."
我使用“public”来表示“这个成员不是一个实现细节”。受保护成员是一个实现细节;为了使派生类工作,需要一些关于它的东西。内部成员是一个实现细节;该程序集内部的其他内容需要该成员才能正常工作。一个公共成员说“这个成员代表了这个对象提供的关键的、记录在案的功能。”
Basically, my attitude is: suppose I decided to make this internal class into a public class. In order to do that, I want to change exactly one thing: the accessibility of the class. If turning an internal class into a public class means that I have to also turn an internal member into a public member, then that member was part of the public surface areaof the class, and it should have been public in the first place.
基本上,我的态度是:假设我决定将这个内部类变成一个公共类。为了做到这一点,我想改变一件事:类的可访问性。如果将内部类转换为公共类意味着我还必须将内部成员转换为公共成员,那么该成员是该类公共表面区域的一部分,它首先应该是公共的。
Other people disagree. There is a contingent that says that they want to be able to glance at the declaration of a member and immediately know whether it is going to be called only from internal code.
其他人不同意。有一种说法是,他们希望能够浏览成员的声明并立即知道它是否仅从内部代码中调用。
Unfortunately, that doesn't always work out nicely; for example, an internal class that implements an internal interface still has to have the implementing members marked as public, because they are part of the public surface of the class.
不幸的是,这并不总是很好。例如,实现内部接口的内部类仍然必须将实现成员标记为公共,因为它们是类的公共表面的一部分。
回答by Ryan P
internalsays the member can only be accessed from within the same assembly. Other classes in that assembly can access the internal publicmember, but would not be able to access a privateor protectedmember, internalor not.
internal表示该成员只能从同一程序集中访问。该程序集中的其他类可以访问该internal public成员,但不能访问private或protected成员internal。
回答by Oded
I suspect that "it is easier to make the type public later?" is it.
我怀疑“以后公开类型会更容易吗?” 是吗。
The scoping rules mean that the method will only be visible as internal- so it really doesn't matter whether the methods are marked publicor internal.
作用域规则意味着该方法只会在 as 中可见internal- 因此,方法是标记为public还是internal.
One possibility that comes to mind is that the class waspublic and was later changed to internaland the developer didn't bother to change all the method accessibility modifiers.
想到的一种可能性是该类是公共的,后来被更改为internal,开发人员没有费心更改所有方法可访问性修饰符。
回答by Mario Corchero
It's the same, the public method will be really marked as internal since it's inside a internal class, but it has an advantaje(as you guested), if you want to mark the class as public, you have to change fewer code.
是一样的,公共方法将被真正标记为内部,因为它在内部类中,但它有一个优点(正如您所描述的),如果您想将该类标记为公共,您必须更改更少的代码。
回答by ?iamond ?eeze?
I often mark my methods in internal classes public instead of internal as a) it doesn't really matter and b) I use internal to indicate that the method is internal on purpose (there is some reason why I don't want to expose this method in a public class. Therefore, if I have an internal method I really have to understand the reason why it's internal before changing it to public whereas if I am dealing with a public method in an internal class I really have to think about why the class is internal as opposed to why each method is internal.
我经常在内部类中将我的方法标记为 public 而不是 internal 作为 a) 这并不重要 b) 我使用 internal 来表示该方法是有意为内部的(有一些原因我不想公开这个公共类中的方法。因此,如果我有一个内部方法,我真的必须在将其更改为公共方法之前了解其内部方法的原因,而如果我正在处理内部类中的公共方法,我真的必须考虑为什么类是内部的,而不是为什么每个方法都是内部的。
回答by Guvante
If the class is internal, it doesn't matter from an accessibility standpoint whether you mark a method internalor public. However it is still good to use the type you would use if the class were public.
如果类是internal,从可访问性的角度来看,标记方法internal还是标记public. 但是,如果类是public.
While some have said that this eases transitions from internalto public. It also serves as part of the description of the method. Internalmethods typically are considered unsafe for unfettered access, while publicmethods are considered to be (mostly) free game.
虽然有人说这简化了从internal到 的转换public。它也作为方法描述的一部分。Internal对于不受限制的访问,方法通常被认为是不安全的,而public方法被认为(主要是)免费游戏。
By using internalor publicas you would in a publicclass, you ensure that you are communicating what style of access is expected, while also easing the work required to make the class publicin the future.
通过像在课堂上那样使用internal或public,您可以public确保传达预期的访问方式,同时还可以减轻public将来制作课程所需的工作。
回答by Trevor Pilley
In some cases, it may also be that the internal type implements a public interface which would mean that any methods defined on that interface would still need to be declared as public.
在某些情况下,也可能是内部类型实现了一个公共接口,这意味着在该接口上定义的任何方法仍然需要声明为公共的。
回答by Storm
I actually struggled with this today. Until now I would have said that methods should all be marked with internalif the class was internaland would have considered anything else simply bad coding or laziness, specially in enterprise development; however, I had to sub class a publicclass and override one of it's methods:
我今天实际上为此而苦苦挣扎。到现在为止,我会说,internal如果该类曾经internal并且会考虑其他任何简单的糟糕编码或懒惰,特别是在企业开发中,那么方法都应该被标记;但是,我必须子类化一个public类并覆盖它的方法之一:
internal class SslStreamEx : System.Net.Security.SslStream
{
public override void Close()
{
try
{
// Send close_notify manually
}
finally
{
base.Close();
}
}
}
The method MUST be publicand it got me thinking that there's really no logical point to setting methods as internalunless they really must be, as Eric Lippert said.
正如 Eric Lippert 所说,方法必须是public,它让我认为设置方法真的没有逻辑意义,internal除非它们真的必须是。
Until now I've never really stopped to think about it, I just accepted it, but after reading Eric's post it really got me thinking and after a lot of deliberating it makes a lot of sense.
直到现在我从来没有真正停下来思考过,我只是接受了它,但是在阅读了 Eric 的帖子后,它真的让我思考了,经过深思熟虑后,这很有意义。
回答by Farrah Jiang
There does be a difference. In our project we have made a lot of classes internal, but we do unit test in another assembly and in our assembly info we used InternalsVisibleTo to allow the UnitTest assembly to call the internal classes. I've noticed if internal class has an internal constructor we are not able to create instance using Activator.CreateInstance in the unit test assembly for some reason. But if we change the constructor to public but class is still internal, it works fine. But I guess this is a very rare case (Like Eric said in the original post: Reflection).
确实有区别。在我们的项目中,我们在内部创建了很多类,但是我们在另一个程序集中进行了单元测试,并且在我们的程序集信息中,我们使用 InternalsVisibleTo 来允许 UnitTest 程序集调用内部类。我注意到如果内部类有一个内部构造函数,由于某种原因,我们无法在单元测试程序集中使用 Activator.CreateInstance 创建实例。但是如果我们将构造函数更改为 public 而 class 仍然是内部的,它就可以正常工作。但我想这是一个非常罕见的案例(就像 Eric 在原帖:Reflection 中所说的那样)。
回答by Hix
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 patternformed 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 有什么意义。然后我到这里结束,读到如果你以后决定将课程改为公开课程可能会很好。真的。所以,在我的脑海中形成了一个模式:如果它不改变当前的行为,那么就宽容,并允许在当前代码状态下没有意义(并且不会伤害)的事情,但以后它会,如果你更改类的声明。
Like this:
像这样:
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 privatemethod, since you can not inherit the class. But if you delete the sealedconstraint, 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 protectedmembers in a sealedclass. Moreover, I have found full agreement, about that it is senseless: 'Protected member in sealed class' warning (a singleton class)
根据我上面提到的“模式”,这应该没问题。它遵循相同的想法。它表现为一种private方法,因为您不能继承该类。但是如果删除sealed约束,它仍然有效:继承的类可以看到这个方法,这绝对是我想要实现的。但是您会收到警告:CS0628, 或CA1047。它们都是关于不要protected在sealed类中声明成员。此外,我发现完全同意,关于它是毫无意义的:“密封类中的受保护成员”警告(单例类)
So after this warning and the discussion linked, I have decided to make everything internal or less, in an internal class, because it conforms more that kind of thinking, and we don't mix different "patterns".
所以在这个警告和相关的讨论之后,我决定把所有东西都放在内部或更少,在一个内部类中,因为它更符合那种思维,我们不混合不同的“模式”。

