
C#のinternalについて分かりやすく解説!|C#のinternalを正しく使いこなそう
- SE
- C#でpublicやprivateは分かるのですが、同じアクセス修飾子のinternalはどのような機能を持っているのですか。
- PM
- internalは同じアセンブリならアクセスできます。アセンブリとはexeやdllのことです。
目次
C#のinternalとは?
C#にはinternalというキーワードがありますが、使ったことが無いので分からない人も多いのではないでしょうか。
internalとはアクセス修飾子の一つですが、何か分からない人もいるのではないでしょうか。まずはそこから説明しましょう。
アクセス修飾子は、クラスとそのメンバーのフィールド・メソッドのアクセスできる範囲を定める機能を持っています。あるクラスのメソッドをどこからでも呼べるようにしたい、もしくは隠してクラスの中でしか呼べないようにしたい、といった時に使用します。
6種類のアクセス制御子
C#のアクセス制御子には以下の6種類があります。C#をある程度使っている人なら、publicやprivateについてはご存じでしょう。
public あらゆる所からアクセスできる
private 同じクラス内のみアクセスできる
protected 同じクラスと派生したクラスのみアクセスできる
internal 同じアセンブリならアクセスできる
protected internal 同じアセンブリと別アセンブリの派生クラスでアクセスできる
private protected 同じクラスと同じアセンブリの派生したクラスのみアクセスできる
アセンブリとは何か?
C#の6つのアクセス修飾子について、publicとprivateはわかると思います。protectedも、派生した子クラスからも呼べると言えば理解できるでしょう。
しかしinternalの「同じアセンブリならアクセスできる」はピンとこないのではないでしょうか。internalを理解するには、アセンブリの意味を分かる必要があります。簡単に言うと、アセンブリとはexeやdllのことです。
同じアセンブリとは同じプロジェクトのこと
アセンブリはexeやdllのこと、とだけ言われても、まだよくわからないと思います。Visual Studioの場合で言えば、同じアセンブリ内とは同じプロジェクト内ということです。具体的にC#のサンプルで見て行きましょう。
class TestClass
{
internal string str;
}
class Program
{
public static void Main()
{
TestClass t = new TestClass();
t.str = “”a””;
}
}
internalは別のクラスからアクセスできる
上のサンプルのTestClassクラスとProgramクラスは同じファイル内に記述しています。TestClassのstrフィールドはinternalが付いていて、ProgramのMainメソッドからアクセスできています。このようにinternalは同じファイルの別のクラスからアクセスすることができます。
では、次に別ファイルのクラスで試しましょう。Visual Studioのソリューションエクスプローラーでプロジェクトのプロパティを右クリックして、追加から新しい項目でTestClass.csを追加してください。
internalは別ファイルのクラスからもアクセスできる
TestClass.csのクラスにinternalのフィールドを追加してください。なおnamespaceのTestAppはプロジェクト名によって違います。
namespace TestApp
{
class TestClass
{
internal string str;
}
}
そしてMainメソッドに以下のように記述してください。internalのフィールドにアクセスできることがわかります。
public static void Main()
{
TestApp.TestClass t = new TestApp.TestClass();
t.str = “”a””;
}
internalとpublicの違いはdllを作ると分かる
ここまで読んで、「これってpublicと同じじゃない?」と思った人もいるのではないでしょうか。その通りで、ここまで行ったことをinternalではなくpublicでやっても、同じようにアクセスできます。
internalとpublicの違いは、dllを作るとわかります。その前にまずexeやdllについて簡単に説明しましょう。Visual Studioで言えば、コンソールアプリのプロジェクトがexe、クラスライブラリのプロジェクトがdllになります。
コンソールアプリのプロジェクトにはMainメソッドがあり、ビルドするとWindows上で動作するexeファイルが作られます。クラスライブラリのプロジェクトで出来るのはdllファイルで、これはexeファイルから参照して使用します。dllは単体で動作しませんが、exeでよく使う共通処理を入れるために使うもので、ライブラリとも呼ばれます。
dllを作成する
それではdllを作成しましょう。まずVisual Studioで新規にC#のクラスライブラリのプロジェクトを作成してください。名前はTestDllとします。そしてTestDllのcsファイルに以下のように記述してソリューションをビルドしてください。
namespace TestDll
{
public class TestClass
{
public string p_str;
internal string i_str;
}
}
そしてVisual Studioのメニューのファイルから最近使ったプロジェクトとソリューションで、今まで使っていたMainメソッドのあるプロジェクトに戻ってください。プロジェクトを閉じて立ち上げ直すよりも、ずっと速く切り替えられます。
プロジェクトにdllを追加する
そしてソリューションエクスプローラーの「依存関係」をクリックし「COM参照を追加」を選択してください。次に参照マネージャーの右下の「参照(B)」ボタンを押してから、Test.dllを選択します。
なおTest.dllのある場所は「C:\Users\(ユーザー名)\source\repos\TestDll\TestDll\bin\Debug\netstandard2.0」ですが、環境によって少し違うかもしれません。
internalは別のアセンブリからはアクセスできない
dllが追加できれば、依存関係のアセンブリにTestDllが追加されます。
それではMainメソッドに以下を記述しましょう。
public static void Main()
{
TestDll.TestClass t = new TestDll.TestClass();
t.p_str = “”a””;
t.i_str = “”b””;
}
するとp_strへのアクセスは問題なくできますが、i_strはエラーになります。これはi_strがp_strと違い、publicではなくinternalだからです。internalは同じアセンブリ、つまり同じexeかdllからしかアクセスできないということが分かって頂けたのではないでしょうか。
protected internalについて
最後にprotected internalについて説明しましょう。プロジェクトをTestDllに切り替えて、C#のソースを以下のように修正してください。そしてソリューションをビルドします。
namespace TestDll
{
public class TestClass
{
public string p_str;
protected internal string i_str;
}
}
dllのクラスを派生してprotected internalにアクセスする
そしてMainメソッドのあるプロジェクトに切り替えて、C#のソースを以下のように記述してください。
class SubClass : TestDll.TestClass
{
public void SetISTR(string str)
{
i_str = str;
Console.WriteLine(i_str + “”を代入しました。””);
}
}
class Program
{
public static void Main()
{
SubClass s = new SubClass();
s.SetISTR(“”abc””);
}
}
protected internalはinternalより融通が利く
上のC#ソースのSubClassは、dllのTestClassを派生した子クラスということです。実行すると以下が表示されます。
abcを代入しました。
このようにprotected internalは、別のアセンブリからでも派生クラスならアクセスすることができるのです。ただし以下のように派生せずにアクセスした場合は、internalと同様にエラーになります。
TestDll.TestClass t = new TestDll.TestClass();
t.i_str = “”b””;
- SE
- internalはdllを作成するためにも知っておく必要がありそうですね。
- PM
- その通りです。protected internalの理解のためにも必要な知識です。
internalをアクセス制御に活用しよう
C#のinternalについて解説しましたが、ご理解頂けましたでしょうか。
internalはdll内で自由に使いたいものの、外部には公開したくないフィールドやメソッドには有効に活用できますね。