访问修饰符(C# 编程指南)
所有类型和类型成员都具有可访问性级别。 该级别可以控制是否可以从你的程序集或其他程序集中的其他代码中使用它们。 程序集是通过在单个编译中编译一个或多个 .cs 文件而创建的 .dll 或 .exe。 可以使用以下访问修饰符在进行声明时指定类型或成员的可访问性:
- 公共:任何程序集中的代码都可以访问此类型或成员。 包含类型的可访问性级别控制该类型的公共成员的可访问性级别。
- 专用:只有在同一
class
或struct
中声明的代码才能访问此成员。 - 受保护:只有同一
class
或派生的class
中的代码才能访问此类型或成员。 - 内部:只有同一程序集中的代码才能访问此类型或成员。
- 受保护的内部:只有同一程序集中的代码或另一个程序集的派生类中的代码才能访问此类型或成员。
- 专用受保护:只有同一程序集和同一类/派生类中的代码才能访问该类型或成员。
- 文件:只有同一文件中的代码可以访问类型或成员。
类型上的 record
修饰符会导致编译器合成额外的成员。 record
修饰符不会影响 record class
或 record struct
的默认可访问性。
摘要表
调用方的位置 | public |
protected internal |
protected |
internal |
private protected |
private |
file |
---|---|---|---|---|---|---|---|
在文件中 | ✔️️ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
在类内 | ✔️️ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ |
派生类(相同程序集) | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ❌ |
非派生类(相同程序集) | ✔ | ✔ | ❌ | ✔ | ❌ | ❌ | ❌ |
派生类(不同程序集) | ✔ | ✔ | ✔ | ❌ | ❌ | ❌ | ❌ |
非派生类(不同程序集) | ✔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
下面的示例演示如何在类型和成员上指定访问修饰符:
public class Bicycle
{
public void Pedal() { }
}
不是所有访问修饰符都可以在所有上下文中由所有类型或成员使用。 在某些情况下,包含类型的可访问性会限制其成员的可访问性。
分部类或分部成员的多个声明必须具有相同的可访问性。 如果分部类或成员的一个声明不包含访问修饰符,则其他声明不能声明访问修饰符。 如果分部类或分部方法的多个声明声明了不同的可访问性,编译器会生成错误。
类和结构可访问性
直接在命名空间中声明的类和结构(没有嵌套在其他类或结构中)可以具有 public
、internal
或 file
。 如果未指定任何访问修饰符,则默认设置为 internal
。
结构成员(包括嵌套的类和结构)可以声明为 public
、internal
或 private
。 类成员(包括嵌套的类和结构)可以声明为 public
、protected internal
、protected
、internal
、private protected
或 private
。 默认情况下,类成员和结构成员(包括嵌套的类和结构)的访问级别为 private
。
派生类不能具有高于其基类型的可访问性。 不能声明派生自内部类 A
的公共类 B
。 如果允许这样,则它将具有使 A
公开的效果,因为可从派生类访问 A
的所有 protected
或 internal
成员。
可以通过使用 InternalsVisibleToAttribute
启用特定的其他程序集访问内部类型。 有关详细信息,请参阅友元程序集。
其他类型
在命名空间内直接声明的接口可以声明为 public
或 internal
,就像类和结构一样,接口默认设置为 internal
访问级别。 接口成员默认为 public
,因为接口的用途是启用其他类型以访问类或结构。 接口成员声明可以包含任何访问修饰符。 在 interface
成员上使用访问修饰符来提供接口的所有实现者所需的通用实现。
默认情况下,在命名空间中声明的 delegate
类型具有 internal
访问权限。
有关访问修饰符的详细信息,请参阅可访问性级别页面。
成员可访问性
可以使用六种访问类型中的任意一种来声明 class
或 struct
的成员(包括嵌套的类和结构)。 结构成员无法声明为 protected
、protected internal
或 private protected
,因为结构不支持继承。
通常情况下,成员的可访问性不大于包含该成员的类型的可访问性。 但是,如果 internal
类的 public
成员实现了接口方法或替代了在公共基类中定义的虚拟方法,则可从该程序集的外部访问该成员。
为字段、属性或事件的任何成员的类型必须至少与该成员本身具有相同的可访问性。 同样,任何方法、索引器或委托的返回类型和参数类型必须至少与该成员本身具有相同的可访问性。 例如,除非 C
也是 public
,否则不能具有返回类 C
的 public
方法 M
。 同样,如果 A
声明为 private
,则不能具有类型 A
的 protected
属性。
用户定义的运算符始终必须声明为 public
和 static
。 有关详细信息,请参阅运算符重载。
若要设置 class
或 struct
成员的访问级别,请向成员声明添加适当的关键字,如以下示例中所示。
// public class:
public class Tricycle
{
// protected method:
protected void Pedal() { }
// private field:
private int _wheels = 3;
// protected internal property:
protected internal int Wheels
{
get { return _wheels; }
}
}
终结器不能具有可访问性修饰符。 enum
类型的成员始终为 public
,并且不能应用访问修饰符。
仅允许在顶级(非嵌套)类型声明中使用 file
访问修饰符。
C# 语言规范
有关详细信息,请参阅 C# 语言规范。 该语言规范是 C# 语法和用法的权威资料。