アクセサーのアクセシビリティの制限 (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 アクセス修飾子をアクセサー自体に適用することにより、明示的に制限されています。
アクセス修飾子によるアクセサーの制限
プロパティやインデクサーでアクセス修飾子を使用する際には、以下の条件が適用されます。
アクセス修飾子は、インターフェイスや明示的なインターフェイス メンバー実装で使用できません。
アクセス修飾子を使用できるのは、プロパティやインデクサーが set と get の両方のアクセサーを備えている場合に限られます。 この場合、修飾子は、これら 2 つのアクセスのうちの一方でのみ許可されます。
プロパティやインデクサーにオーバーライド修飾子がある場合、アクセス修飾子は、オーバーライドされたアクセサーのアクセサーに一致する必要があります。
アクセサーのアクセシビリティ レベルは、プロパティやインデクサー自体のアクセシビリティ レベルよりも制限する必要があります。
アクセサーのオーバーライド時のアクセス修飾子
プロパティやインデクサーをオーバーライドした場合、オーバーライドされたアクセサーは、オーバーライド側のコードにアクセスできる必要があります。 また、プロパティとインデクサーの両方のアクセシビリティ レベル、およびアクセサーのアクセシビリティ レベルは、オーバーライドされた、対応するプロパティとインデクサー、およびアクセサーに適合する必要があります。 次に例を示します。
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 つのアクセサーを使用してインターフェイスを実装する場合は、次の例に示すように、もう 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 { }
}
}
アクセサーのアクセシビリティ ドメイン
アクセサーでアクセス修飾子を使用した場合は、この修飾子によって、アクセサーのアクセシビリティ ドメインが決定されます。
アクセサーでアクセス修飾子を使用しない場合は、プロパティやインデクサーのアクセシビリティ レベルによって、アクセサーのアクセシビリティ ドメインが決定されます。
使用例
次の例には、BaseClass、DerivedClass、MainClass の 3 つのクラスがあります。 BaseClass には Name と Id の 2 つのプロパティがあり、これらのプロパティは派生クラスにもあります。 この例は、protected や private などの制限付きのアクセス修飾子を使用したときに、DerivedClass の Id プロパティを BaseClass の Id プロパティによってどのように隠ぺいできるかを示しています。 そのため、前者のプロパティに値を割り当てると、代わりに BaseClass クラスのプロパティが呼び出されます。 アクセス修飾子を public に置き換えると、このプロパティにアクセスできるようになります。
また、次の例は、private や protected などの制限付きのアクセス修飾子を、DerivedClass の Name プロパティの set アクセサーに指定すると、このアクセサーにアクセスできなくなり、このプロパティに値を割り当てると、エラーが生成されることも示しています。
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