1. 程式人生 > 實用技巧 >C#中,程式碼能不能訪問到private或protected的成員,和當前程式碼是不是在型別(類、結構體)中有關,和當前程式碼是不是在型別(類、結構體)的物件例項中無關

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)

            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的,儘管它是通過基類BaseClass繼承到的,但是DerivedClass類的intProtectedMember成員,終究是DerivedClass類自己的,並不是BaseClass類的那個intProtectedMember成員,所以我們在AccessProtectedMember和AccessProtectedMemberWithinInstance方法中,無法通過BaseClass類的物件例項baseClass,來訪問到BaseClass類的protected成員intProtectedMember,也就合情合理了,因為AccessProtectedMember和AccessProtectedMemberWithinInstance方法實際上是被定義在子類DerivedClass中,並不是在基類BaseClass中。

好了,其實通過本文,我們就可以瞭解到private和protected的成員,能不能被訪問到,實際上是和當前程式碼是否在定義成員的型別(類、結構體)中有關,並不是說只能在定義成員的型別(類、結構體)物件例項程式碼中才能訪問到它們。

參考文獻:

Access Modifiers (C# Programming Guide)