成员的“已声明可访问性”可以是下列之一:
- Public,选择它的方法是在成员声明中包括
public
修饰符。public
的直观含义是“访问不受限制”。 - Protected,选择它的方法是在成员声明中包括
protected
修饰符。protected
的直观含义是“访问范围限定于它所属的类或从该类派生的类型”。 - Internal,选择它的方法是在成员声明中包括
internal
修饰符。internal
的直观含义是“访问范围限定于此程序”。 - Protected internal(意为受保护或内部的),选择它的方法是在成员声明中包括
protected
和internal
修饰符。protected
internal
的直观含义是“访问范围限定于此程序或那些由它所属的类派生的类型”。 - Private,选择它的方法是在成员声明中包括
private
修饰符。private
的直观含义是“访问范围限定于它所属的类型”。
声明一个成员时所能选择的已声明可访问性的类型,依赖于该成员声明出现处的上下文。此外,当成员声明不包含任何访问修饰符时,声明发生处的上下文会为该成员选择一个默认的已声明可访问性。
- 命名空间隐式地具有
public
已声明可访问性。在命名空间声明中不允许使用访问修饰符。 - 编译单元或命名空间中声明的类型可以具有
public
或internal
已声明可访问性,默认的已声明可访问性为internal
。 - 类成员可具有五种已声明可访问性中的任何一种,默认为
private
已声明可访问性。(请注意,声明为类成员的类型可具有五种已声明可访问性中的任何一种,而声明为命名空间成员的类型只能具有public
或internal
已声明可访问性。) - 结构成员可以具有
public
、internal
或private
已声明可访问性并默认为private
已声明可访问性,这是因为结构是隐式地密封的。结构的成员若是在此结构中声明的(也就是说,不是由该结构从它的基类中继承的)不能具有protected
或protected
internal
已声明可访问性。(请注意,声明为结构成员的类型可具有public
、internal
或private
已声明可访问性,而声明为命名空间成员的类型只能具有public
或internal
已声明可访问性。) - 接口成员隐式地具有
public
已声明可访问性。在接口成员声明中不允许使用访问修饰符。 - 枚举成员隐式地具有
public
已声明可访问性。在枚举成员声明中不允许使用访问修饰符。
一个成员的可访问域由(可能是不连续的)程序文本节组成,从那里可以访问该成员。出于定义成员可访问域的目的,如果成员不是在某个类型内声明的,就称该成员是顶级的;如果成员是在其他类型内声明的,就称该成员是嵌套的。此外,程序的程序文本定义为包含在该程序的所有源文件中的全部程序文本,而类型的程序文本定义为包含在该类型(可能还包括嵌套在该类型内的类型)的“类体”、“结构体”、“接口体”或“枚举体”中的开始和结束(“{
”和“}
”)标记之间的全部程序文本。
预定义类型(如 object
、int
或 double
)的可访问域是无限制的。
在程序 P
中声明的顶级类型 T
的可访问域如下定义:
- 如果
T
的已声明可访问性为public
,则T
的可访问域是P
的以及引用P
的任何程序的程序文本。 - 如果
T
的已声明可访问性为internal
,则T
的可访问域是P
的程序文本。
从这些定义可以推断出:顶级类型的可访问域始终至少是声明了该类型的程序的程序文本。
在程序 P
内的类型 T
中声明的嵌套成员 M
的可访问域如下定义(注意 M 本身可能就是一个类型):
- 如果
M
的已声明可访问性为public
,则M
的可访问域是T
的可访问域。 - 如果
M
的已声明可访问性是protected
internal
,设D
表示P
的程序文本和从T
派生的任何类型(在P
的外部声明)的程序文本的并集。M
的可访问域是T
与D
的可访问域的交集。 - 如果
M
的已声明可访问性是protected
,则设D
表示T
的程序文本和从T
派生的任何类型的程序文本的并集。M
的可访问域是T
与D
的可访问域的交集。 - 如果
M
的已声明可访问性为internal
,则M
的可访问域是T
的可访问域与P
的程序文本的交集。 - 如果
M
的已声明可访问性为private
,则M
的可访问域是T
的程序文本。
从这些定义可以看出:嵌套成员的可访问域总是至少为声明该成员的类型的程序文本。还可以看出:成员的可访问域包含的范围决不会比声明该成员的类型的可访问域更广。
用直观的话来讲,当访问类型或成员 M
时,按下列步骤进行计算以确保允许进行访问:
- 首先,如果
M
是在某个类型(相对于编译单元或命名空间)内声明的,则当该类型不可访问时将会发生编译时错误。 - 然后,如果
M
为public
,则允许进行访问。 - 否则,如果
M
为protected
internal
,则当访问发生在声明了M
的程序中,或发生在从声明M
的类派生的类中并通过派生类类型(第 3.5.3 节)进行访问时,允许进行访问。 - 否则,如果
M
为protected
,则当访问发生在声明了M
的类中,或发生在从声明M
的类派生的类中并通过派生类类型(第 3.5.3 节)进行访问时,允许进行访问。 - 否则,如果
M
为internal
,则当访问发生在声明了M
的程序中时允许进行访问。 - 否则,如果
M
为private
,则当访问发生在声明了M
的类型中时允许进行访问。 - 否则,类型或成员不可访问,并发生编译时错误。
在下面的示例中,
public class A { public static int X; internal static int Y; private static int Z; } internal class B { public static int X; internal static int Y; private static int Z; public class C { public static int X; internal static int Y; private static int Z; } private class D { public static int X; internal static int Y; private static int Z; } }
类和成员具有下列可访问域:
A
和A.X
的可访问域无限制。A.Y
、B
、B.X
、B.Y
、B.C
、B.C.X
和B.C.Y
的可访问域是包含程序的程序文本。A.Z
的可访问域是A
的程序文本。B.Z
和B.D
的可访问域是B
的程序文本,包括B.C
和B.D
的程序文本。B.D.X
和B.D.Y
的可访问域是B
的程序文本,包括B.C
和B.D
的程序文本。B.D.Z
的可访问域是B.D
的程序文本。
如示例所示,成员的可访问域决不会大于包含它的类型的可访问域。例如,即使所有的 X
成员都具有公共级的已声明可访问性,但除了 A.X
外,所有其他成员的可访问域都受包含类型的约束。
如第 3.4 节中所描述的那样,基类的所有成员(实例构造函数、析构函数和静态构造函数除外)都由派生类型继承。这甚至包括基类的私有成员。但是,私有成员的可访问域只包括声明该成员的类型的程序文本。在下面的示例中,
class A { int x; static void F(B b) { b.x = 1; // Ok } } class B: A { static void F(B b) { b.x = 1; // Error, x not accessible } }
类 B
继承类 A
的私有成员 x
。因为该成员是私有的,所以只能在 A
的“类体”中对它进行访问。因此,对 b.x
的访问在 A.F
方法中取得了成功,在 B.F
方法中却失败了。