アクセサーのアクセシビリティの制限 (C# プログラミング ガイド)

プロパティまたはインデクサーの get および set 部分は、アクセサーと呼ばれます。 既定では、これらのアクセサーは、それらが属するプロパティまたはインデクサーと同じ可視性またはアクセス レベルを持っています。 詳細については、「アクセシビリティ レベル」を参照してください。 しかし、これらのアクセサーのいずれかへのアクセスを制限すると便利な場合があります。 通常、set アクセサーのアクセシビリティを制限しながら、get アクセサーのパブリック アクセスを維持します。 次に例を示します。

private string _name = "Hello";

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

この例では、Name というプロパティが get および set アクセサーを定義します。 get アクセサーは、プロパティ自体のアクセシビリティ レベル (この場合は public) を受け取り、同時に set アクセサーは、protected アクセサー修飾子をアクセサー自体に適用することによって明示的に制限されます。

注意

この記事の例では、自動実装プロパティは使用しません。 自動実装プロパティは、カスタム バッキング フィールドが必要ない場合にプロパティを宣言するための簡潔な構文を提供します。

アクセサーのアクセス修飾子の制限

プロパティまたはインデクサーでのアクセサー修飾子の使用は、以下の条件の対象になります。

  • インターフェイスまたは明示的な interface メンバーの実装でアクセサー修飾子を使用することはできません。
  • アクセサー修飾子は、プロパティまたはインデクサーに setget アクセサーの両方がある場合にのみ使用できます。 この場合、修飾子は、2 つのアクセサーのいずれかでのみ許可されます。
  • プロパティまたはインデクサーに 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 などの 1 つのアクセサーを使用してインターフェイスを実装する場合、他のアクセサーは、次の例のように、アクセス修飾子を持つことができます。

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 { }
    }
}

アクセサー アクセシビリティ ドメイン

アクセサーでアクセス修飾子を使用する場合、アクセサーのアクセシビリティ ドメインはこの修飾子によって決まります。

アクセサーでアクセス修飾子を使用しなかった場合、アクセサーのアクセシビリティ ドメインは、プロパティまたはインデクサーのアクセシビリティ レベルによって決まります。

次の例は、BaseClassDerivedClass、および MainClass という 3 つのクラスを含んでいます。 すべてのクラスの BaseClassNameId に 2 つのプロパティがあります。 この例は、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 Idnew public string Id によって置き換えた場合、次の出力を取得します。

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

関連項目