C#のアクセス修飾子を書かなかった場合に関して
背景
C#のアクセス修飾子(public, private, internal, protected など)については、C#の基本的事項として、入門書や入門者向けホームページにもほぼ間違いなく記載されている基本的な事項です。
しかし、(特にホームページで)publicやprivateを付けるとどうなるかの解説はほとんどの記事に含まれていますが、もし、何も付けなかったらどうなるかが書かれていないことがよく見受けられます。
また、それらはたいていメソッドや、フィールド、プロパティなど、クラス内のメンバに関してであり、クラスにつけるprivateやpublicについてどうなるかについてもあまり記述がありません。
今回は、以上の2点が今ひとつ分からなかったため、それらを解決すべく、C#のアクセス修飾子(access modifier)についてC#の仕様書(C# Language Specification, 英語, 約500ページ)のアクセス修飾子に関する部分を読んでみましたC#の仕様書は、英語ですが簡単にダウンロードできます今回は、読んで私が先ほどの分からなかった点のうち、特に何も付けなかった場合に関する部分について理解したことをメモしておきます。詳細は直接仕様書へどうぞ。
メンバ(Members)とは
C#のコードには、名前空間の中にクラス、クラスの中にメソッドのように、階層構造があります。この階層構造があるということが重要です。そして、その最上位がグローバル名前空間(Global namespace)です。そして、各階層名前空間やクラスなどのすぐ下の階層にある要素クラスやメソッドなどのことをメンバ(Members)と呼びます。
ここではそれぞれの要素が持ちうるメンバーを示します。また、型(type)とは、構造体(struct)、列挙体(enumeration)、クラス(class)などを指しますが、話を省略するため、型の代表としてクラスを利用して説明します。
- グローバル名前空間
- 名前空間
- クラス
- 名前空間
- クラス
- クラス
- クラス
- 定数
- フィールド
- プロパティ
- メソッド
- イベント
- インデクサ
- 演算子
以降、名前空間AのメンバにクラスBがあるとき、名前空間Aを、クラスBの親メンバ、クラスBを名前空間Aの子メンバと呼ぶことで、わかりやすくしたいと思います。つまり、「この要素をメンバとして持つ要素」を「親メンバ」と呼びます。
5つのアクセシビリティ(Declared accessibility)
ここでは、まず要素の持ちうる5種類のアクセシビリティを紹介します。要素に対してこの5つ以外のアクセシビリティが与えられることはありません。必ず要素はいずれかのアクセシビリティを持ちます。あくまでアクセス修飾子と区別するために、すべて大文字にしてあります。
- PUBLIC
アクセスは「制限されない」("access not limited") - PROTECTED
アクセスは、「親メンバ内部」および「親メンバクラスを継承した型の内部」に制限される("access limited to the containing class or types derived from the containing class") - INTERNAL
アクセスは、「この要素が含まれるプログラム(アセンブリ, .exe, .dll)」に制限される("access limited to this program") - PROTECTED INTERNAL
アクセスは、「この要素が含まれるプログラム」および「親メンバクラスを継承した型」に制限される("access limited to this program or types derived from the containing class") - PRIVATE
アクセスは、「親メンバ」に制限される"access limited to the containing type"
あとは、それぞれの要素がどのアクセシビリティを持つかが問題です。
アクセシビリティの決定方法
ここでは、どのアクセシビリティになるかがどう決まるかを説明します。基本は簡単です。
- public, protected, internal, protected internal, privateのアクセス修飾子があるばあいは、それぞれPUBLIC, PROTECTED, INTERNAL, PROTECTED INTERNAL, PRIVATEのアクセシビリティとなる。
-
アクセス修飾子が存在しない場合は、それぞれのデフォルトアクセシビリティとなる。ここで、それぞれの要素のデフォルトアクシビリティは次のように定義される。ただし、要素のデフォルトアクセシビリティが、その要素の親メンバのアクセシビリティとは無関係に事前に決められていることに注意。
- 名前空間
PUBLIC - 型(入れ子にされていないクラス、構造体など)
INTERNAL - クラスの子メンバ(メソッド、入れ子にされた型など)
PRIVATE - 構造体の子メンバ
PRIVATE - インターフェイス
PUBLIC - 列挙型
PUBLIC
- 名前空間
以上を使うことで、すでに記述されているC#のコードのアクセシビリティを判断できると思います。実は、これ自体だけでは、結局正確にどこからアクセス可能かは判断できません。それに関しては、あまりに量が多いのでもうあきらめます。
ところで、これだけでは、自分でコードを記述するときに、どのようなアクセス修飾子を記述可能なのかは分かりません。それについては次です。
要素に付けて良いアクセス修飾子(C#言語仕様 3.5.1節より)
アクセス修飾子(public, protected, internal, protected internal, private)は、付けて良い場所と、付けては行けない場所があります。付けていけない場所に付けると、「名前空間で定義された要素は明示的に private、protected、または protected internal に宣言することはできません」のようなコンパイルエラーが発生してしまいます。以下、それぞれの要素に付けられるアクセス修飾子をまとめました。
- 名前空間
付けられない。 - 型(入れ子にされていないクラス、構造体など)
public、internal - クラスの子メンバ(メソッド、入れ子にされた型など)
public、protected、internal、protected internal、private - 構造体の子メンバ
public、internal、private - インターフェイス
付けられない。 - 列挙型
付けられない。
まとめ
以上、メモでしたが、このエントリのタイトル「C#のアクセス修飾子を書かなかった場合に関して」、つまり、public, protected, internal, protected internal, privateのいずれもしていなかったときどうなるかは、次のようにまとめられます。
- 名前空間
PUBLIC - 型(入れ子にされていないクラス、構造体など)
INTERNAL - クラスの子メンバ(メソッド、入れ子にされた型など)
PRIVATE - 構造体の子メンバ
PRIVATE - インターフェイス
PUBLIC - 列挙型
PUBLIC
見ての通り、前述した、「デフォルトアクセシビリティ」になる、ということですね。
感想
本当に困ったら、言語仕様を読むのが一番よさそうですね。ただ、次に紹介するmsdnには、同じことが優しく書いてあったりするので、そちらをまず参考にすることをおすすめします。
参考文献
- C# Language Specification Version 3.0(英語)
- 3.4 Members
- 3.5.1 Declared accessibility
- 3.5.2 Accessibility domains
- 10.3 Class members
- 10.3.5 Access modifires
- C# リファレンス(msdn)
- C# プログラミングガイド(msdn)
書籍で読みたいなら、定番の「Programming C#」もしくは、その訳著「プログラミング C#
」がおすすめ。msdnで十分だとは思うけど、本がいい人向け。
おまけ
Programming C# 4.0
が Programming C# 第6版 として2010年4月15日(@amazon)に発売されます。もちろん、英語ですが、これの日本語版が出るのはだいぶ先と思われます。C# 4.0の増えた部分が結構多いので、チェックしてみては。