一、C#中已声明的可访问性
1. public:访问不受限制;
2. internal:访问仅限于所属程序集;
3. protected:访问仅限于当前类和其子类;
4. internal protected:访问仅限于当前程序集或其子类(子类可以不属于当前程序集);
5. private:访问仅限于包含该成员的类型。
二、默认可访问性
1. 命名空间(namespace)隐式地具有public访问性,且不允许有访问修饰符;
2. 编辑单元或命名空间中声明的类型可以具有public或internal可访问性,默认为internal;
3. 类(class)的默认访问级别为internal;
4. 结构体(struct)默认访问级别为private;
5. 接口(interface)默认访问基本为internal;但是如果在其他public类中使用时,必须为public;
6. 类和结构体成员(成员函数和成员变量)默认访问级别为private;(但是声明为命名空间成员的类型只能具有public或internal可访问性);
7. 接口的成员隐式地具有public可访问性,在接口成员的声明中不允许使用访问修饰符;
6. 枚举的成员隐式地具有public可访问性,声明中不允许使用访问修饰符。
三、可访问性约束
1. 类类型的直接基类必须至少与该类类型本身具有相同的可访问性;
2. 接口类型的基接口必须至少与该接口类型本身具有相同的可访问性;
3. 委托类型的返回类型和参数类型必须至少与该委托类型本身具有相同的可访问性;
4. 常量的类型必须至少与该常量本身具有相同的可访问性;
5. 域的类型必须至少与该域本身具有相同的可访问性;
6. 方法的返回类型和参数类型必须至少与该方法本身具有相同的可访问性;
7. 属性的类型必须至少与该属性本身具有相同的可访问性;
8. 事件的类型必须至少与该事件本身具有相同的可访问性;
9. 索引器的类型和参数类型必须与该索引器本身具有相同的可访问性;
10. 运算符的返回类型和参数类型必须至少与该运算符本身具有相同的可访问性;
11. 实例构造函数的参数类型必须至少与该实例构造函数本身具有相同的可访问性。
四、可访问域
1. 预定义类型(例如object、int或double)可访问域是无限的;
2. 在程序P中声明的顶级类型(不是在某个类型中声明的成员)T的可访问域是指:
1).如果T的已声明可访问性为public,则T的可访问域将是P以及引用P的任何程序的程序文本;
2).如果T的已声明可访问性为internal,则T的可访问域将是P的程序文本。
可见,定及类型的可访问域始终至少是在其中声明该类型的程序的程序文本。
3. 在程序P的类型T中声明的嵌套成员(在其他类型中声明的成员)M,其可访问域是如下所指之一(M本身也可能是一个类型):
1).如果M的已声明可访问性为public,则M的可访问域将是T的可访问域;
2).如果M的已声明可访问性为internal protected,设D表示P的程序文本和所有从T派生的类型(这些类型是在P的外部声明的)的程序文本的并集,则M的可访问域将是T与D的可访问域的交集;
3).如果M的已声明可访问性为protected,设D表示T的程序文本和所有从T派生的类型的程序文本的并集,则M的可访问域将是T与D的可访问域的交集;
4).如果M的已声明可访问性为internal,则M的可访问域将是T的可访问域与P的程序文本的交集;
5).如果M的已声明可访问性为private,则M的可访问域将是T的程序文本。
可见,嵌套成员的可访问域总是至少为声明该成员的类型的程序文本,并且绝不会大于声明该成员的类型的可访问域。
例
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;
}
}
在这个例子中,类和成员具有以下可访问域:
1) A和A.X的可访问域无限制;
2) A.Y、B、B.X、B.Y、B.C、B.C.X和B.C.Y的可访问域是包含这段代码的程序的程序文本;
3) A.Z的可访问域是A的程序文本;
4) B.Z和B.D的可访问域是B的程序文本,包括B.C和B.D的程序文本;
5) B.C.Z的可访问域是B.C的程序文本;
6) B.D.X和B.D.Y的可访问域是B的程序文本,包括B.C和B.D的程序文本;
7) B.D.Z的可访问域是B.D的程序文本。
例:基类的所有成员(实例构造函数、析构函数和静态构造函数除外)都由派生类型继承,这些成员甚至包括基类的私有成员。然而,私有成员的可访问域只包括声明该成员的类型的程序文本。在下面的示例中,类B继承了类A的私有成员x:
class A
{
int x; //类的成员的默认可访问性为private
static void F(B b){
b.x = 1; //允许
}
}
class B: A
{
static void F(B b){
b.x = 1; //错误,不能访问x
}
}
由于该成员是私有的,所以只能在A的类主体中对他进行访问。因此,A.F方法中对b.x的访问可以成功,但是B.F方法中对b.x的访问却会造成错误。