限制存取子的存取範圍 (C# 程式設計手冊)

屬性或索引子的 getset 部分稱為「存取子」。 根據預設,這些存取子具有其所屬屬性或索引子的相同可見度或存取層級。 如需詳細資訊,請參閱存取範圍層級。 然而,有時限制其中一個存取子的存取權十分實用。 一般而言,您會限制 set 存取子的協助工具,同時保留可公開存取的 get 存取子。 例如:

private string _name = "Hello";

public string Name
{
    get
    {
        return _name;
    }
    protected set
    {
        _name = value;
    }
}

在此範例中,稱為 Name 的屬性定義 getset 存取子。 get 存取子會接收屬性本身的存取範圍階層 (在此情況下為 public),同時將 protected 存取修飾詞套用至存取子本身以明確限制 set 存取子。

注意

本文中的範例不會使用自動實作屬性。 當不需要自訂支援欄位時,自動實作屬性會提供簡潔的語法來宣告屬性。

存取子的存取修飾詞限制

在屬性或索引子上使用存取子修飾詞受限於這些條件:

  • 您無法在介面或明確介面成員實作上使用存取子修飾詞。
  • 只有在屬性或索引子同時具有 setget 存取子時,才能使用存取修飾詞。 在此情況下,允許只在兩個存取子的其中一個上使用修飾詞。
  • 如果屬性或索引子具有 override 修飾詞,則存取子修飾詞必須符合已覆寫存取子的存取子 (如果有的話)。
  • 存取子上的存取範圍層級必須比屬性或索引子本身上的存取範圍層級更為嚴格。

覆寫存取子上的存取修飾詞

當您覆寫屬性或索引子時,覆寫端程式碼必須可以存取覆寫的存取子。 此外,屬性/索引子及其存取子的存取範圍必須符合已覆寫的對應屬性/索引子及其存取子。 例如:

public class Parent
{
    public virtual int TestProperty
    {
        // Notice the accessor accessibility level.
        protected set { }

        // No access modifier is used here.
        get { return 0; }
    }
}
public class Kid : Parent
{
    public override int TestProperty
    {
        // Use the same accessibility level as in the overridden accessor.
        protected set { }

        // Cannot use access modifier here.
        get { return 0; }
    }
}

實作介面

當您使用存取子實作介面時,存取子不能有存取修飾詞。 不過,如果您使用一個存取子 (例如 get) 實作介面,其他存取子可以有存取修飾詞,如下列範例所示:

public interface ISomeInterface
{
    int TestProperty
    {
        // No access modifier allowed here
        // because this is an interface.
        get;
    }
}

public class TestClass : ISomeInterface
{
    public int TestProperty
    {
        // Cannot use access modifier here because
        // this is an interface implementation.
        get { return 10; }

        // Interface property does not have set accessor,
        // so access modifier is allowed.
        protected set { }
    }
}

存取子存取範圍定義域

如果您在存取子上使用存取修飾詞,這個修飾詞會判斷存取子的存取範圍定義域

若您未在存取子上使用存取修飾詞,則屬性或索引子的協助工具層級會判斷存取子的協助工具網域。

範例

下列範例包含三個類別:BaseClassDerivedClassMainClass。 這兩個類別的 BaseClassNameId 上有兩個屬性。 此範例示範當您使用 protectedprivate 這類限制存取修飾詞時,BaseClass 上的 Id 屬性可以隱藏 DerivedClass 上的 Id 屬性。 因此,當您將值指派給這個屬性時,會改為呼叫 BaseClass 類別上的屬性。 將存取修飾詞取代為 public 會將屬性設為可存取。

此範例也會示範 DerivedClassName 屬性之 set 存取子上的 privateprotected 等限制性存取修飾詞防止存取衍生類別中的存取子。 當您指派給該屬性或存取相同名稱的基底類別屬性時,會產生錯誤。

public class BaseClass
{
    private string _name = "Name-BaseClass";
    private string _id = "ID-BaseClass";

    public string Name
    {
        get { return _name; }
        set { }
    }

    public string Id
    {
        get { return _id; }
        set { }
    }
}

public class DerivedClass : BaseClass
{
    private string _name = "Name-DerivedClass";
    private string _id = "ID-DerivedClass";

    new public string Name
    {
        get
        {
            return _name;
        }

        // Using "protected" would make the set accessor not accessible.
        set
        {
            _name = value;
        }
    }

    // Using private on the following property hides it in the Main Class.
    // Any assignment to the property will use Id in BaseClass.
    new private string Id
    {
        get
        {
            return _id;
        }
        set
        {
            _id = value;
        }
    }
}

class MainClass
{
    static void Main()
    {
        BaseClass b1 = new BaseClass();
        DerivedClass d1 = new DerivedClass();

        b1.Name = "Mary";
        d1.Name = "John";

        b1.Id = "Mary123";
        d1.Id = "John123";  // The BaseClass.Id property is called.

        System.Console.WriteLine("Base: {0}, {1}", b1.Name, b1.Id);
        System.Console.WriteLine("Derived: {0}, {1}", d1.Name, d1.Id);

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
/* Output:
    Base: Name-BaseClass, ID-BaseClass
    Derived: John, ID-BaseClass
*/

註解

請注意,如果您將宣告 new private string Id 取代為 new public string Id,則會取得輸出:

Name and ID in the base class: Name-BaseClass, ID-BaseClass Name and ID in the derived class: John, John123

另請參閱