連載:[完全版]究極のC#プログラミング

Chapter9 プロパティとアクセシビリティ

川俣 晶
2009/11/30
Page1 Page2

 本記事は、(株)技術評論社が発行する書籍『[完全版]究極のC#プログラミング ― 新スタイルによる実践的コーディング』から、許可を得て転載しています。
 同書籍は、もともと本フォーラムにて連載していた『C# 2.0入門』、『C# 3.0入門』の記事を整理統合し、加筆、修正されたものです。

手元でまとめて読みたい方は、ぜひ書店などにてお買い求めください。

 【注意】本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

9.1 プロパティアクセサのアクセシビリティ

 C# 3.0では、プロパティのsetアクセサとgetアクセサに対して、異なるアクセシビリティを制限できる。これにより、getアクセサはpublicだが、setアクセサはprotectedという非対称のプロパティを宣言できる。

 書き方は簡単で、getまたはsetキーワードの手前に、アクセシビリティを指定するキーワードを追加するだけである。それによって、プロパティ宣言そのものに付いているアクセシビリティ指定を上書きする(リスト9.1参照)。

using System;

class A
{
  private string s;

  public string SampleProp // 本来public指定だが……
  {
    get { return s; } // 本来のpublic指定が有効
    protected set { s = value; } // protectedで上書きしている
  }
}

class B : A
{
  public void Initialize()
  {
    SampleProp = "by class B";
  }
}

class Program
{
  static void Main(string[] args)
  {
    B b = new B();
    b.Initialize();
    Console.WriteLine(b.SampleProp); // 出力:by class B
  }
}
リスト9.1 getはpublicだがsetはprotectedの例

 さて、この機能は継承が絡むとややこしい問題を併発する場合がある。その事例を紹介しよう。

 次のリスト9.2は、継承関係のある2つのクラスの双方が同じ名前のプロパティを宣言している例である。このコードでは、クラスBのSamplePropプロパティはprotectedなので、外部からはアクセスできない。だから、Mainメソッドが利用しているのはクラスAのSamplePropである。このように、アクセスできないプロパティをスキップし、アクセスできるプロパティが使われるようになっている。

using System;

class A
{
  private string s;

  public string SampleProp
  {
    get { return s; }
    set { s = value; }
  }
}

class B : A
{
  private string s;

  protected new string SampleProp // protectedなプロパティ
  {
    get { return s; }
    set { s = value; }
  }
}

class Program
{
  static void Main(string[] args)
  {
    B b = new B();
    b.SampleProp = "Sample";
    Console.WriteLine(b.SampleProp); // 出力:Sample
  }
}
リスト9.2 正常に動作するケース

 ここで、クラスBのプロパティをpublicにし、getアクセサとsetアクセサで異なるアクセシビリティを持たせてみよう。リスト9.2のクラスBをリスト9.3の内容に差し替えてみる。

class B : A
{
  private string s;

  public new string SampleProp
  {
    protected get { return s; }
    set { s = value; }
  }
}
リスト9.3 リスト9.2のクラスBを差し替える

 すると、次のようなエラーが起きてコンパイルできない。

get アクセサにアクセスできないため、プロパティまたはインデクサ'B.SampleProp' はこのコンテキストでは使用できません。

 最初の例から考えると、protectedなSamplePropのgetアクセサを飛ばして、クラスAのSamplePropのgetアクセサを使ってくれそうに思えるかもしれないが、そのようには動作していない。get/setの手前のアクセシビリティ指定は、メンバーの検索やオーバーロードの解決には影響しないからである。つまり、getアクセサのprotectedに関係なく、クラスBのpublicなSamplePropプロパティは発見されてしまい、それにprotectedが付いているためにアクセスできないというエラーになるわけである。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter9 プロパティとアクセシビリティ
  1.9.1 プロパティアクセサのアクセシビリティ
    2.9.2 アクセシビリティ指定の制約/練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間