在C#中,private和protected访问修饰符被广泛应用,微软对它们的定义如下:
- private:只有同一 class 或 struct 中的代码可以访问该类型或成员。
- protected:只有同一 class 或者从该 class 派生的 class 中的代码可以访问该类型或成员。
相信大家对这两个访问修饰符的概念已经很熟悉了,这里不再多述。唯一要注意的是结构体中,不能定义protected的成员,只是本文为了叙述方便,将(类、结构体)写在一起了。
本文想解释的是private和protected的成员,能不能被代码访问到,是和当前代码是否在定义private和protected成员的类型(类、结构体)中有关,而不是说一定要当前代码在定义private和protected成员的类型(类、结构体)对象实例中,才能访问到它们。也就是说类型(类、结构体)对象实例的private和protected成员,不是只能通过this和base关键字才能访问到。
定义一个.NET Core控制台项目,我们首先来看看下面关于private访问修饰符的代码:
using System; namespace NetCoreAccess { //BaseClass类 public class BaseClass { private int intPrivateMember = 1000; protected int intProtectedMember = 1000; //静态方法AccessPrivateMember,访问BaseClass类的private成员intPrivateMember public static int AccessPrivateMember(BaseClass baseClass) { int result = baseClass.intPrivateMember; BaseClass anotherBaseClass = new BaseClass(); result = anotherBaseClass.intPrivateMember; return result; } } class Program { static void Main(string[] args) { Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
可以看到,我们可以在BaseClass类的静态方法AccessPrivateMember中,访问到类BaseClass对象实例baseClass和anotherBaseClass的private成员intPrivateMember。这就是因为静态方法AccessPrivateMember,是定义在BaseClass类中的,所以它就可以访问到BaseClass类的private成员intPrivateMember,尽管AccessPrivateMember方法不属于任何BaseClass类的对象实例。
现在,我们增加关于protected访问修饰符的代码,如下所示:
using System; namespace NetCoreAccess { //BaseClass类 public class BaseClass { private int intPrivateMember = 1000; protected int intProtectedMember = 1000; //静态方法AccessPrivateMember,访问BaseClass类的private成员intPrivateMember public static int AccessPrivateMember(BaseClass baseClass) { int result = baseClass.intPrivateMember; BaseClass anotherBaseClass = new BaseClass(); result = anotherBaseClass.intPrivateMember; return result; } } //DerivedClass类,继承基类BaseClass public class DerivedClass : BaseClass { //静态方法AccessProtectedMember,访问DerivedClass类中,从BaseClass类继承到的protected成员intProtectedMember public static int AccessProtectedMember(DerivedClass derivedClass) { int result = derivedClass.intProtectedMember; DerivedClass anotherDerivedClass = new DerivedClass(); result = anotherDerivedClass.intProtectedMember; BaseClass baseClass = derivedClass; //result = baseClass.intProtectedMember;//编译错误:Error CS1540 Cannot access protected member 'BaseClass.intProtectedMember' via a qualifier of type 'BaseClass'; the qualifier must be of type 'DerivedClass' (or derived from it) baseClass = new BaseClass(); //result = baseClass.intProtectedMember;//编译错误:Error CS1540 Cannot access protected member 'BaseClass.intProtectedMember' via a qualifier of type 'BaseClass'; the qualifier must be of type 'DerivedClass' (or derived from it) return result; } } class Program { static void Main(string[] args) { Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
可以看到,我们可以在DerivedClass类的静态方法AccessProtectedMember中,访问到类DerivedClass对象实例derivedClass和anotherDerivedClass的protected成员intProtectedMember,这就是因为静态方法AccessProtectedMember,是定义在DerivedClass类中的,所以它就可以访问到类DerivedClass中,从基类BaseClass继承到的protected成员intProtectedMember,尽管AccessProtectedMember方法不属于任何DerivedClass类的对象实例。
尽管如此,我们可以从AccessProtectedMember方法中被注释掉的代码看到,我们无法通过基类BaseClass的对象实例baseClass来访问protected成员intProtectedMember,会出现编译错误。也许你会想是不是因为AccessProtectedMember是静态方法,所以我们在它里面无法使用BaseClass类的对象实例,来访问到protected成员intProtectedMember,那我们把代码改为如下,添加DerivedClass类的对象实例方法(非静态方法)AccessProtectedMemberWithinInstance,如下所示:
using System; namespace NetCoreAccess { //BaseClass类 public class BaseClass { private int intPrivateMember = 1000; protected int intProtectedMember = 1000; //静态方法AccessPrivateMember,访问BaseClass类的private成员intPrivateMember public static int AccessPrivateMember(BaseClass baseClass) { int result = baseClass.intPrivateMember; BaseClass anotherBaseClass = new BaseClass(); result = anotherBaseClass.intPrivateMember; return result; } } //DerivedClass类,继承基类BaseClass public class DerivedClass : BaseClass { //静态方法AccessProtectedMember,访问DerivedClass类中,从BaseClass类继承到的protected成员intProtectedMember public static int AccessProtectedMember(DerivedClass derivedClass) { int result = derivedClass.intProtectedMember; DerivedClass anotherDerivedClass = new DerivedClass(); result = anotherDerivedClass.intProtectedMember; BaseClass baseClass = derivedClass; //result = baseClass.intProtectedMember;//编译错误:Error CS1540 Cannot access protected member 'BaseClass.intProtectedMember' via a qualifier of type 'BaseClass'; the qualifier must be of type 'DerivedClass' (or derived from it) baseClass = new BaseClass(); //result = baseClass.intProtectedMember;//编译错误:Error CS1540 Cannot access protected member 'BaseClass.intProtectedMember' via a qualifier of type 'BaseClass'; the qualifier must be of type 'DerivedClass' (or derived from it) return result; } //对象实例方法AccessProtectedMemberWithinInstance,访问DerivedClass类中,从BaseClass类继承到的protected成员intProtectedMember public int AccessProtectedMemberWithinInstance(DerivedClass derivedClass) { int result = derivedClass.intProtectedMember; DerivedClass anotherDerivedClass = new DerivedClass(); result = anotherDerivedClass.intProtectedMember; BaseClass baseClass = derivedClass; //result = baseClass.intProtectedMember;//编译错误:Error CS1540 Cannot access protected member 'BaseClass.intProtectedMember' via a qualifier of type 'BaseClass'; the qualifier must be of type 'DerivedClass' (or derived from it) baseClass = new BaseClass(); //result = baseClass.intProtectedMember;//编译错误:Error CS1540 Cannot access protected member 'BaseClass.intProtectedMember' via a qualifier of type 'BaseClass'; the qualifier must be of type 'DerivedClass' (or derived from it) return result; } } class Program { static void Main(string[] args) { Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
从AccessProtectedMemberWithinInstance方法中被注释掉的代码可以看出,我们仍然无法通过BaseClass类的对象实例baseClass,来访问protected成员intProtectedMember,会出现编译错误。这是因为从本质上来说基类BaseClass和子类DerivedClass是两个不同的类,尽管它们之间有继承关系,但是我们在子类DerivedClass的AccessProtectedMember和AccessProtectedMemberWithinInstance方法中,访问到的protected成员intProtectedMember,都还是属于子类DerivedClass的,尽管intProtectedMember成员是通过基类BaseClass继承到的,但是DerivedClass类的intProtectedMember成员,终究是DerivedClass类自己的,并不是BaseClass类的那个intProtectedMember成员,所以我们在AccessProtectedMember和AccessProtectedMemberWithinInstance方法中,无法通过BaseClass类的对象实例baseClass,来访问到BaseClass类的protected成员intProtectedMember,也就合情合理了,因为AccessProtectedMember和AccessProtectedMemberWithinInstance方法实际上是被定义在子类DerivedClass中,并不是在基类BaseClass中。
好了,其实通过本文,我们就可以了解到private和protected的成员,能不能被访问到,实际上是和当前代码是否在定义成员的类型(类、结构体)中有关,并不是说只能在定义成员的类型(类、结构体)对象实例代码中才能访问到它们。
参考文献:
Access Modifiers (C# Programming Guide)