C# 中提供了 6 种访问修饰符:public、private、protected、internal、protected internal、private protected。
访问修饰符 在所有的类型和类型成员中都具有可访问性级别,用于控制是否可以从程序集或其他程序集中对其他代码的访问控制。
访问修饰符 | 描述 |
---|---|
public | 同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。 |
private | 只有同一 class 或 struct 中的代码可以访问该类型或成员。 |
protected | 只有同一 class 或者从该 class 派生的 class 中的代码可以访问该类型或成员。 |
internal | 同一程序集中的任何代码都可以访问该类型或成员,但其他程序集中的代码不可以。 |
protected internal | 该类型或成员可由对其进行声明的程序集或另一程序集中的派生 class 中的任何代码访问。 |
private protected | 只有在其声明程序集内,通过相同 class 中的代码或派生自该 class 的类型,才能访问类型或成员。 |
下面我创建了一个叫做 AccessControl
的控制台项目,并创建两个类文件:DemoClassOne.cs
、 DemoClassTwo.cs
。
在默认情况下,方法的修饰符为 private
(类的修饰符为 public
),如下代码中,在 DemoClassOne.cs
类中添加了 3 个方法,test1()
与 test2()
为相同的修饰类型( private
),test3()
为 public
类型,可以被所有的引用所访问。
class DemoClassOne
{
static void test1()
{
}
private static void test2()
{
}
public static void test3()
{
}
}
那么在 Program.cs
中调用这三个方法就会出现test1()
与 test2()
不可访问的错误,而 test3()
就没有问题。方法修饰为 public
除了在方法的类里面可以访问,在其它类中也是可以访问的。
class Program
{
static void Main(string[] args)
{
DemoClassOne.test1(); // 不可访问,因为它具有一定的保护级别
DemoClassOne.test2(); // 不可访问,因为它具有一定的保护级别
DemoClassOne.test3(); // 可以正常访问
}
}
总结: public
修饰的方法在同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。
由上面 public
的案例可以知道,private
在外部类中是无法访问的,但是在方法的所在类中却是可以访问的。private
只有在声明它们的类和结构体中才是可访问的
class DemoClassOne
{
static void test1()
{
}
private static void test2()
{
}
public static void test3()
{
test1(); // 在当前类中可以访问默认修饰符的方法
test2(); // 在当前类中可以访问 private 修饰符的方法
test3(); // 在当前类中可以访问 public 饰符的方法,且可以方法递归调用
}
}
总结: private
修饰的方法只有同一 class
或 struct
中的代码可以访问该类型或成员。
在 DemoClassOne
中创建四个方法:test1()、test2()、test3()、test4()。如下代码所示。
class DemoClassOne
{
static void test1()
{
}
private static void test2()
{
}
public static void test3()
{
}
protected static void test4()
{
}
}
在 DemoClassTwo.cs
中的类 DemoClassTwo
继承 DemoClassOne
,并创建方法 test5(),键入如下代码 。由案例可看出,protected
和 public
修饰的方法在子类中可以访问,其他的不能访问。
class DemoClassTwo : DemoClassOne
{
public static void test5()
{
DemoClassOne.test1(); // 不可访问,因为它具有一定的保护级别
DemoClassOne.test2(); // 不可访问,因为它具有一定的保护级别
test3(); // 子类访问父类 public 修饰的方法
test4(); // 子类访问父类 protected 修饰的方法
}
}
同样的,在 Program.cs
中调用 DemoClassOne
中的四个方法,仅有 public
修饰的方法能够有访问权限。
class Program
{
static void Main(string[] args)
{
DemoClassOne.test1(); // 不可访问,因为它具有一定的保护级别
DemoClassOne.test2(); // 不可访问,因为它具有一定的保护级别
DemoClassOne.test3(); // 子类访问父类 public 修饰的方法
DemoClassOne.test4(); // 不可访问,因为它具有一定的保护级别
}
}
总结: protected
修饰的方法只有同一 class
或者从该 class
派生的 class
中的代码可以访问该类型或成员。
在 DemoClassOne.cs
中将类 DemoClassOne
修饰符更改为 internal
添加方法public修饰的方法 test1()。
namespace AccessControl
{
internal class DemoClassOne
{
static void test1()
{
}
}
}
而后在 Program.cs
中调用 DemoClassOne
中的方法会报错。
class Program
{
static void Main(string[] args)
{
DemoClassOne.test1(); // 不可访问,因为它具有一定的保护级别
}
}
那么,我把 DemoClassOne
修饰符 internal
移动到方法 test1() 上,此时方法 test1() 在 AccessControl
项目中均可以访问的到。
class DemoClassOne
{
internal static void test1()
{
}
}
class Program
{
static void Main(string[] args)
{
DemoClassOne.test1(); // 可访问
}
}
接下来,继续在解决方案里面创建一个新的类库项目 AccessControl2
,并创建一个类 AccessControlDemo
,键入如下代码。
namespace AccessControl2
{
public class AccessControlDemo
{
internal static void testDemo()
{
}
public static void testDemo2()
{
}
}
}
此时我们接着回到 AccessControl
项目的 Program.cs
中调用 AccessControl2
中的方法 testDemo()
,此时会发现,并不能访问到这个方法,说明 internal
修饰的方法仅允许在当前项目中使用。
class Program
{
static void Main(string[] args)
{
AccessControlDemo.testDemo(); // 不可访问,因为它具有一定的保护级别
AccessControlDemo.testDemo2(); // public 修饰符的方法可以访问
}
}
总结: protected
修饰的方法或成员,在同一程序集中的任何代码都可以访问该类型或成员,但其他程序集中的代码不可以。。
看到 protected internal
修饰符的名称就知道,这是 protected
和 internal
修饰符的总合,兼并它们两者的特性。也就是说自己与派生类可以访问,同时同一个程序集也可以访问。如下案例,在 AccessControl2
项目的 AccessControlDemo
类中添加了如下代码。
namespace AccessControl2
{
public class AccessControlDemo
{
internal static void testDemo()
{
}
public static void testDemo2()
{
}
protected internal static void testDemo3()
{
}
}
}
在 AccessControl
项目中的 Main
方法中可以看到只能访问 public
修饰的方法,另外两个方法不可访问。
class Program
{
static void Main(string[] args)
{
AccessControlDemo.testDemo(); // 不可访问,因为它具有一定的保护级别
AccessControlDemo.testDemo2(); // public 修饰符的方法可以访问
AccessControlDemo.testDemo3(); // 不可访问,因为它具有一定的保护级别
}
}
在 AccessControl
项目中让类 DemoClassOne
继承 AccessControlDemo
,而后访问 AccessControlDemo
类中的方法,此时发现 testDemo2()
和 testDemo3()
两个方法可以访问,testDemo()
方法不可访问。
using AccessControl2;
namespace AccessControl
{
class DemoClassOne: AccessControlDemo
{
internal static void test1()
{
AccessControlDemo.testDemo(); // 不可访问,因为它具有一定的保护级别
AccessControlDemo.testDemo2(); // public 修饰符的方法可以访问
AccessControlDemo.testDemo3(); // protected internal 修饰的方法在派生类中可访问
}
}
}
总结: protected internal
修饰的类型或成员可由对其进行声明的程序集或另一程序集中的派生 class
中的任何代码访问。
同样的,private protected
也就是 prvate
与 protected
的交集,其具有 protected
的访问特性(在派生类中可访问),但将范围约束在了当前项目,而在其他项目中的派生类是不可以访问的。下面代码演示。
在 AccessControl2
项目中在创建一个类 AccessControlDemo2
,并继承类 AccessControlDemo
,键入如下代码,发现同一项目中是的派生类是可以访问 private protected
修饰的方法的。
namespace AccessControl2
{
class AccessControlDemo2 : AccessControlDemo
{
public static void testDemo5()
{
AccessControlDemo.testDemo4(); // 同一程序集中的派生类中可以访问 private protected 修饰的方法
}
}
}
在 AccessControl
项目中的 DemoClassOne
类中访问 AccessControlDemo.testDemo4()
却是不可以访问的。
namespace AccessControl
{
class DemoClassOne: AccessControlDemo
{
public static void test1()
{
AccessControlDemo.testDemo4(); // 不可访问,因为它具有一定的保护级别
}
}
}
总结: private protected
修饰的类型或成员只有在其声明程序集内,通过相同 class
中的代码或派生自该 class
的类型,才能访问类型或成员。
如果希望一个方法能够被任何程序集或者类访问,那么修饰符设置为 public
;
如果希望一个方法仅仅在当前类中访问,那么修饰符设置为 private
;
如果希望一个方法在仅在派生类中可以访问,包括当前程序集及其他程序集中的派生类,那么修饰符设置为 protected
;
如果希望一个方法仅在当前程序集的任何位置中访问,那么修饰符设置为 internal
;
如果希望一个方法在当前程序集中的任何位置中访问或者其他程序集的派生类中访问,那么修饰符设置为 protected internal
;
如果希望一个方法仅在当前程序集的派生类中访问,那么修饰符设置为 private protected
。
最后说明: 可能这些看起来有点绕,一时没能理解这些修饰符的意思和作用范围,其实可以通过创建一个项目一个个的测试,仔细研读理论讲解,等逐步熟练后就能理清楚它们的关系。这里贴上官方的讲解: 访问修饰符