1. 程式人生 > >C#類訪問修飾符

C#類訪問修飾符

訪問修飾符是一些關鍵字,用於指定宣告的成員或型別的可訪問性。訪問修飾符有四個:

public protected internal private

宣告的可訪問性

含義

public

訪問不受限制。

protected

訪問僅限於包含類或從包含類派生的型別。

internal

訪問僅限於當前程式集。

protected internal

訪問僅限於從包含類派生的當前程式集或型別。

private

訪問僅限於包含型別。

一個成員或型別只能有一個訪問修飾符,使用 protected internal 組合時除外。

名稱空間上不允許使用訪問修飾符。名稱空間沒有訪問限制。

根據發生成員宣告的上下文,只允許某些宣告的可訪問性。如果在成員宣告中未指定訪問修飾符,則使用預設的可訪問性。

不巢狀在其他型別中的頂級型別的可訪問性只能是 internal 或 public。這些型別的預設可訪問性是 internal。

巢狀型別是其他型別的成員,它們可以具有下表所示的宣告的可訪問性。

屬於

預設的成員可訪問性

該成員允許的宣告的可訪問性

enum

public

class

private

public

protected

internal

private

protected internal

interface

public

struct

private

public

internal

private

範例如下:

publicTest

namespace publicTest

{

   class Point

    {

       public int x;

       //private int x;

       //protected int x;

       //internal int x;

       public int y;

    }

}

namespace publicTest

{

   class MainClass

    {

       static void Main()

       {

           Point p = new Point();

            // Direct access to public members:

           p.x = 10;

           p.y = 15;

           Console.WriteLine("x = {0}, y = {1}", p.x, p.y);

           Console.ReadLine();

       }

    }

}

在同一程式集下,定義Point類下的成員為public與internal,可直接通過 MainClass 訪問 Point 的公共成員 x 和 y。

protectedTest

namespace protectedTest

{

   class A

    {

       protected int x = 123;

       //public int x = 123;

    }

}

namespace protectedTest

{

   class B : A

    {

       static void Main()

       {

           A a = new A();

           B b = new B();

           // Error CS1540, because x can only be accessed by

           // classes derived from A.

           // a.x = 10;

           // OK, because this class derives from A.

           b.x = 10;

           //Console.WriteLine("{0} {1}", a.x, b.x);

           Console.WriteLine(b.x);

           Console.ReadLine();

       }

    }

}

在B中呼叫類A的建構函式,建立一個物件a。然後獲取a.x會報CS1540錯誤,在網上也搜了好久。搜到瞭如下資訊:protected型別並不是能夠被派生類隨心所欲的訪問,而是有條件的,訪問必須是通過派生類型別發生時,在派生類中的基類的protected型別成員才能夠被訪問,這裡就很清楚了上面的程式碼並不是通過派生類的型別訪問的,而是通過基類的型別訪問的,此時此刻,protected和private十分的相似,只不過,protected型別成員能夠被派生類所繼承並且能夠通過派生類型別訪問罷了。

namespace protectedTest

{

   class Point

    {

       protected int x;

       protected int y;

    }

}

namespace protectedTest

{

   class DerivedPoint : Point

    {

       static void Main()

       {

           DerivedPoint dp = new DerivedPoint();

           // Direct access to protected members:

           dp.x = 10; dp.y = 15;

           Console.WriteLine("x = {0}, y = {1}", dp.x, dp.y);

           Console.ReadLine();

       }

    }

}

privateTest

namespace privateTest

{

   class Employee

    {

       private string name = "FirstName, LastName";

       private double salary = 100.0;

       public string GetName()

       {

           return name;

       }

       public double Salary

       {

           get { return salary; }

       }

    }

}

namespace privateTest

{

   class MainClass

    {

       static void Main()

       {

           Employee e = new Employee();

           // The data members are inaccessible (private), so

           // then can't be accessed like this:

           //string n = e.name;

           //double s = e.salary;

           // 'name' is indirectly accessed via method:

           string n = e.GetName();

           // 'salary' is indirectly accessed via property

           double s = e.Salary;

           Console.WriteLine("{0} {1}",n,s);

           Console.ReadLine();

       }

    }

}

MainClass無法直接訪問物件的name和salary成員,需要屬性或者方法。C#的類有field(欄位)和Attribute(屬性)。欄位用小寫,並且是不對外暴露,也就是說是私有或者是保護變數(id)。外部如果要操作(讀、寫)這些欄位,需要通過對外暴露出來的屬性(ID)的get(讀)、set(寫)操作。

internalTest

namespace internalTest

{

    internal class BaseClass

    {

       public static int intM = 0;

    }

   //public class BaseClass

   //{

   //    public static int intM = 0;

   //}

}

namespace Assembly

{

   class TestAccess

    {

       static void Main()

       {

           BaseClass myBase = new BaseClass();  // CS0122

       }

    }

}

不在一個程式集中, “internalTest.BaseClass.BaseClass()”不可訪問,因為它受保護級別限制。

使用public

namespace internalTest

{

   public class BaseClass_B

    {

       internal static int intM = 0;

    }

}

namespace Assembly

{

   public class TestAccess_B

    {

       static void Main()

       {

           BaseClass_B myBase = new BaseClass_B();  // Ok.

           myBase.intM = 444;    // CS0117

       }

    }

}

會報出錯誤:無法使用例項引用來訪問成員“internalTest.BaseClass_B.intM”;請改用型別名來限定它,因為intM在internalTest中為靜態方法。

靜態成員也稱為共享成員,例如靜態屬性 靜態欄位 靜態方法;靜態成員可以在類的例項之間共享。靜態類中只能有靜態成員,不能有例項成員,因為靜態類不能進行例項化;在非靜態類中即可以有靜態成員也可以有非靜態成員;只要是靜態成員 屬性 欄位 方法,都需要用類名去呼叫;當類第一次載入的時候(第一次被載入到記憶體的時候),該類下的所有的靜態成員都會被載入,例項成員有多少個物件,就會建立多少個物件;靜態成員會被載入到靜態儲存區,直到程式退出時才會被釋放;

修改後程式碼:

namespace Assembly

{

   public class TestAccess_B

    {

       static void Main()

       {

           BaseClass_B myBase_B = new BaseClass_B();   // Ok.

           BaseClass_B.intM = 444;

       }

    }

}