C#中,代码能不能访问到private或protected的成员,和当前代码是不是在类型(类、结构体)中有关,和当前代码是不是在类型(类、结构体)的对象实例中无关

在C#中,privateprotected访问修饰符被广泛应用,微软对它们的定义如下:

  • private:只有同一 class 或 struct 中的代码可以访问该类型或成员。
  • protected:只有同一 class 或者从该 class 派生的 class 中的代码可以访问该类型或成员。

相信大家对这两个访问修饰符的概念已经很熟悉了,这里不再多述。唯一要注意的是结构体中,不能定义protected的成员,只是本文为了叙述方便,将(类、结构体)写在一起了。

本文想解释的是privateprotected的成员,能不能被代码访问到,是和当前代码是否在定义privateprotected成员的类型(类、结构体)中有关,而不是说一定要当前代码在定义privateprotected成员的类型(类、结构体)对象实例中,才能访问到它们。也就是说类型(类、结构体)对象实例的privateprotected成员,不是只能通过thisbase关键字才能访问到。

新建一个.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)

            baseClass = this;
            //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中。

好了,其实通过本文,我们就可以了解到privateprotected的成员,能不能被访问到,实际上是和当前代码是否在定义成员的类型(类、结构体)中有关,并不是说只能在定义成员的类型(类、结构体)对象实例代码中才能访问到它们。

参考文献:

Access Modifiers (C# Programming Guide)