C#を勉強しなおしてみた(3)
アクセス修飾子と範囲

どもです。

前回前々回に引き続き、今回もC#のお勉強の内容について書いていきます。

今回は、アクセス修飾子とアクセス可能な範囲について書いていきます。

1. アクセス修飾子

現在、C#で指定可能なアクセス修飾子は、以下の通りです。

  • public
  • protected
  • private
  • internal
  • protected internal
  • private protected

これらのアクセス修飾子とクラスのメンバーへのアクセス制御について、書いていきます。

1.1. public/protected/private

まず、「public/protected/private」の基本的なアクセス修飾子です。表にまとめると、以下のようになります。

アクセス修飾子 アクセス範囲
public どこからでもアクセス可能
(同一アセンブリ(バイナリ)の他のクラス、または外部アセンブリからもアクセス可能)
protected
  • 同じクラス内、および派生クラス内からのみアクセス可能
  • 同じクラス内の他のクラスからはアクセス不可
private
  • 同じクラス内からのみアクセス可能
  • 他のクラス、外部からはアクセス不可

先述の通り、これら3つのアクセス修飾子は、他のオブジェクト指向に対応したプログラミング言語でも使われています。C#だからといって、その内容に大きな違いはありません。

そのため、これ以上の詳細な説明はしません。

1.2. internal

次に、internalです。

internalアクセス修飾子は、他の言語にはない修飾子です。

internalを付与されたクラスのメンバーのアクセス範囲は、以下の通りです。

  • 同じアセンブリ内であれば、どのクラスからもアクセス可能。
  • 他のアセンブリからは、アクセス不可能。

internalなメンバーへのアクセス制御は、publicとよく似ています。違いは、「他のアセンブリからアクセスできるか否か」になります。この「他のアセンブリ」からの「アクセス」を制御するということから、internal修飾子はライブラリの開発で効果を発揮すると考えています。即ち、以下のような場合です。

外部には公開したくないが、内部で共有したい機能、あるいは情報へのアクセスを制限し、不正/不要なアクセスを防御する。

文字だけでは分かりにくいと思いますので、テキトーなサンプルコードを書いて確認します。

1.2.1. 確認する内容

internal修飾子について、実際にコードを書いて、アクセス可能な範囲を確認します。確認する内容は、以下の通りです。

  • DLL内でクラスにアクセスする(同じアセンブリ内からアクセス)
    • publicなクラスのpublicなメソッドにアクセスする
    • publicなクラスのinternalなメソッドにアクセスする
    • internalなクラスのpublicなメソッドのアクセスする
    • internalなクラスのintenralなメソッドにアクセスする
  • DLLのクラスにアクセスする(他のアセンブリからアクセスする)
    • publicなクラスのpublicなメソッドにアクセスする
    • publicなクラスのinternalなメソッドにアクセスする
    • internalなクラスのpublicなメソッドのアクセスする
    • internalなクラスのintenralなメソッドにアクセスする

実際のコードです。まずは、「DLLのクラス」です

namespace ClassLibrary1
{
	/// 
	/// publicなクラス
	/// 
	public class Class1
	{
		/// 
		/// publicなメソッド
		/// 
		/// 外部からアクセスする用
		public int SampleMethod_001()
		{
			var closedClass = new ClosedClass_001();

			return closedClass.SampleMethod_001();
		}

		/// 
		/// internalなメソッド
		/// 
		/// 外部からアクセスする用
		internal int SampleMethod_002()
		{
			var closedClass = new ClosedClass_001();

			return closedClass.SampleMethod_001();
		}

		/// 
		/// publicなメソッド
		/// 
		/// internalなクラスからアクセスする用
		public int SampleMethod_003()
		{
			return 1;
		}

		/// 
		/// intrernalなメソッド
		/// 
		/// internalなクラスからアクセスする用
		internal int SampleMethod_004()
		{
			return 1;
		}
	}

	/// 
	/// internalなクラス
	/// 
	internal class ClosedClass_001
	{
		/// 
		/// publicなメソッド
		/// 
		/// publicなクラスからアクセスする用
		public int SampleMethod_001()
		{
			var cls1 = new Class1();

			// internalなクラスのpublicなメソッドから、
			// publicなクラスのpublicなメソッドへアクセス
			return cls1.SampleMethod_003();
		}

		/// 
		/// internalなメソッド
		/// 
		/// publicなクラスからアクセスする用
		internal int SampleMethod_002()
		{
			var cls1 = new Class1();

			// internalなクラスのinternalなメソッドから、
			// publicなクラスのinternalなメソッドへアクセス
			return cls1.SampleMethod_004();
		}
	}
}

このコードのVisualStudioのエディタのスクリーンショットは、以下の通りです。



見ての通り、特にエラーが表示されません。そのため、「同じアセンブリ内からアクセス」ではpublicからinternal、またはinternalからpublicにアクセスすることはできるようです。

次に、「DLLのクラスにアクセスする(他のアセンブリからアクセスする)」コードです。

using ConsoleApp3;

var sample1 = new SampleClass();

var class1 = new ClassLibrary1.Class1();
int result1 = class1.SampleMethod_001();
int result2 = class1.SampleMethod_Cls2();

var closedClass1 = new ClassLibrary1.ClosedClass_001();

このコードのVisualStudioのエディタのスクリーンショットは、以下の通りです。



見ての通り、アクセスレベルをinternalに設定したメソッド、あるいはクラスに赤い下線が表示されており、ここでエラーとなることが示されています。実際にこのコードをビルドすると、赤い下線の場所においてメソッドが見つからない、あるいは「アクセスできない保護レベルになっている」ことが原因のエラーが発生します。

1.3. protected internal

次に、protected internalです。

protected internalアクセス修飾子はinternal修飾子同様、他の言語にはない修飾子です。

protected internalを付与されたクラスのメンバーのアクセス範囲は、以下の通りです。

  • 同じアセンブリのどのクラスからもアクセス可能
  • 同じアセンブリ内の、派生クラスからもアクセス可能。
  • 他のアセンブリからは、アクセス不可能

protected internalなクラスあるいはメンバーに対するアクセス可能な範囲は、他のアセンブリからアクセスできないこと以外、internalと同じです。

1.4. private protected

最後に、private protectedです。

private protectedアクセス修飾子も、他の言語にはない修飾子です。

private protectedアクセス修飾子を指定したメンバへのアクセス範囲は、以下の通りです。

  • 同じアセンブリ内の派生クラスからのみアクセス可能
  • 同じアセンブリ内の外部クラスからはアクセス不可能
  • 他のアセンブリからはアクセス不可能

2. まとめ

今回は、C#で指定可能なアクセス修飾子について書きました。

C#ではpublic、protected、private、internal、protected internal、private protectedの全6種類のアクセス修飾子が指定可能です。

C#の修飾子の特徴として、internalがあります。この修飾子を使用することで、外部に公開したくないが内部では参照できるようにしたい、といった少し複雑なアクセス範囲の設定が可能となります。

またinternalとprotected、あるいはprivateとprotectedを組み合わせたアクセス修飾子も指定可能です。これら組み合わせたアクセス修飾子を使用することで、アクセス可能範囲をより細かく設定することができます。

次回は、関数の引数の渡し方について書いてみます。

ではっ!