C#中的内部和公共区别

126

我想了解在IT技术中,publicinternal访问修饰符之间的区别。

在类中何时应该使用internal,何时应该使用public?我对方法何时应该是publicinternal感到困惑。

我了解到internal可以通过程序集进行访问,而public也可以通过程序集进行使用。 那么它们的区别在哪里?

8个回答

133

public表示可以从任何位置访问。

internal则只能在一个程序集内访问。

通常情况下,我们使用internal来保护内部的API。例如,你可以暴露一个方法的多个重载:

public int Add(int x, int y)
public int Add(int x,int y, int z)

两者都调用了内部方法:

internal int Add(int[] numbers)

你可以在一个方法上添加很多复杂的东西,但通过使用门面方法“保护”它,可以帮助程序员正确地调用该方法。(例如,带有数组参数的实现方法可能具有任意值的限制。)

还值得注意的是,使用反射,无论其可见性如何,都可以调用任何方法。这是控制/访问内部隐藏API的另一种“黑客”方式。


5
在一个内部类中,我可以声明公共方法吗? - NoviceToDotNet
不行,这会导致冲突。编译器会提示错误并无法编译。 - Program.X
17
实际上,你是可以这样做的,而编译器不会给出任何提示。 - O. R. Mapper
实际上,我是通过谷歌搜索来到这里的,想知道这是否真的是一个功能。想象一下将类internal和所有方法public。如果需要更高的可见性,可以再次将整个类设置为public。但我不确定它是否应该以这种方式使用。所以我继续谷歌搜索... 编辑 Et voilà,同样的主题:https://dev59.com/xGox5IYBdhLWcg3wSCfk - ecth
你可以通过在 AssemblyInfo.cs 文件中添加以下行来使内部方法对其他程序集可见:[assembly:InternalsVisibleTo("MyOtherProject")] - Sergio Prats

45

internal 对于想要在 DLL 内部声明成员或类型而不是在外部声明的情况非常有用。

通常,当你将成员声明为 public 时,你可以从其他 DLL 中访问它。但是,如果你需要将某些东西声明为仅在类库内部公开,则可以将其声明为 internal

在正式的定义中,internal 成员仅在当前程序集内可见。


21

internal 在编写单元测试时非常有用。 InternalsVisibleTo 属性允许测试程序集访问代码程序集中的内部方法。也就是说,您可以测试外部世界认为是私有的方法,而不必使用反射。


1
非常感谢!我正在搜索这个问题,因为单元测试无法访问内部方法。 - Tahirhan

6

公共(Public)也可以在程序集外部访问。因此,当您有一个类不应该被所有程序集中的类都能访问时,请使用 internal。如果需要从外部访问,则使用 public。


使用“public”而不是“internal”可能会导致一些实际的副作用或问题,为典型的商店提供一些例子可能会有所帮助。对于较小的应用程序,通常不会将应用程序源代码分成多个程序集。虽然库可能在不同的程序集中,但它们通常可以通过反射来窥视“internal”项。 - FloverOwe

5
一般来说,public方法应该符合非常高的健壮性标准(不会因为错误输入而导致崩溃或破坏数据)和安全意识标准(不允许意外的输入触发漏洞利用)。但对于internalprotectedprivate方法,通常可以遵循更为宽松的标准,因为每个方法都有完全控制自身接收的输入。
由于从public方法传递的参数(可能来自外部源)被认为比从代码程序集内部接收到的参数不够可信,所以标记为public的方法通常会被代码分析器与标记为internal的同名方法有所不同。举个例子,对于一个public方法,分析器可能会警告需要检查该方法的参数不是null值。而对于internal方法,分析器可能会配置为对null检查更加宽松。或者分析器可能通过对程序集所有源文件进行流分析,确定永远不会将null作为参数传递给特定的方法,并因此确定无需检查参数是否为null。还有许多其他分析器对publicinternal方法处理不同的例子。
通过正确标记类、方法、属性、字段、接口等具有正确访问修饰符的元素,您可以向代码分析器正确传递您的意图,进而获得更相关的警告信息和建议。

4
此外,被标记为internal的属性在WPF中用于数据绑定时会抛出BindingExpression path error。因此,这些属性必须是public才能正常工作,即使数据绑定发生在同一程序集中。

0
用非常简单的语言来说:
Internal:你只能在程序集内部访问。 例如:如果你创建了一个名为 AccountService.csproj 的程序集,并且其中包含一个 internal 类。
public interface IAccount{

  int TotalAmount(long accountID);
}
internal class Account:IAccount{
  
  public int TotalAmount(long accountID){
       ...
   }
}
public class Customer{
   
 public long accountID {get;set;}
 public int GetTotalAmount(){
   IAccount account = new Account();
   return account.TotalAmount(accountID)
 }
}

如果您正在引用 AccountService.csproj 到 BankService.csproj (BankService.csproj --> AccountService.csproj)

Below are the properties that accessible in BankService.csProj    
Customer.GetTotalAmount() -- Accessible
IAccount.TotalAmount()    -- Accessible
Account.TotalAmount()     -- Not Accessible (as account class is internal)

-4
如果您可以从外部引用程序集,则可以访问内部和公共类的范围。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接