C# における internal と public の違いとエラーの原因

C# では、クラスやメソッドのアクセス範囲を制御するために アクセス修飾子 を使用します。特に internalpublic を適切に使わないと、アクセス権に関するエラーが発生することがあります。

1. internal と public の違い

アクセス修飾子説明
publicどこからでもアクセス可能(他のアセンブリからも可能)
internal同じアセンブリ内からのみアクセス可能(外部アセンブリからは不可)

アセンブリ(Assembly)とは、C# のプロジェクトをビルドしたときに生成される .exe.dll のことを指します。

2. アセンブリと Windows フォームアプリの関係

Windowsフォームアプリ(WinFormsアプリ)では、通常プロジェクトごとに1つのアセンブリとして考えます。

例えば、以下のようなソリューションを考えます。

MySolution (ソリューション)
│── MyWinFormsApp (Windowsフォームアプリ) → `MyWinFormsApp.exe`
│── MyLibrary (クラスライブラリ) → `MyLibrary.dll`
  • MyWinFormsApp.exeメインの実行ファイル で、ここに internal なクラスを作ると アプリ内でのみ利用可能 になります。
  • MyLibrary.dll外部ライブラリ で、他のプロジェクトと共有できますが、internal のクラスは MyLibrary.dll の中だけで有効 になります。
  • MyWinFormsApp から MyLibrary.dllinternal メンバーにアクセスするには InternalsVisibleTo を設定する必要があります。

3. internal クラスの public メンバーにアクセスできない例

以下のように internal クラスの public メソッドを別のアセンブリから使おうとすると、エラーになります。

// AssemblyA にあるクラス
internal class InternalClass
{
    public void PublicMethod() { }
}
// AssemblyB からアクセスを試みる
class AnotherClass
{
    void Test()
    {
        InternalClass obj = new InternalClass(); // エラー!
        obj.PublicMethod(); // ここもエラー!
    }
}

この場合、PublicMethod()public ですが、そのクラス InternalClassinternal のため、外部のアセンブリ(AssemblyB)からは そもそもクラスが見えない ためエラーになります。

4. public クラスの internal メソッドにアクセスできない例

逆に、public クラスの中に internal メソッドを作ると、クラス自体は見えるのにメソッドが使えないという状況が発生します。

// AssemblyA にあるクラス
public class PublicClass
{
    internal void InternalMethod() { }
}
// AssemblyB からアクセスを試みる
class AnotherClass
{
    void Test()
    {
        PublicClass obj = new PublicClass(); // クラスは見える
        obj.InternalMethod(); // エラー!
    }
}

この場合、PublicClasspublic なので AnotherClass からインスタンスを作成できますが、InternalMethod()internal なので、外部アセンブリ(AssemblyB)からはアクセスできません。

5. 解決策

(1) internalpublic に変更する

外部アセンブリからアクセスさせたい場合、internalpublic に変更することで解決できます。

public class InternalClass
{
    public void PublicMethod() { }
}

ただし、無闇に public にすると セキュリティやカプセル化の観点で問題 になる場合があります。

(2) InternalsVisibleTo を使用する

特定のアセンブリだけに internal メンバーを公開したい場合、InternalsVisibleTo 属性を使用できます。

設定方法:

  1. AssemblyA の AssemblyInfo.cs に以下を追加
[assembly: InternalsVisibleTo("AssemblyB")]
  1. これにより、AssemblyB から AssemblyAinternal クラスやメソッドにアクセス可能になります。

6. まとめ

  • internal同じアセンブリ内でのみ アクセス可能。
  • publicどのアセンブリからも アクセス可能。
  • internal クラスの public メソッドは、クラス自体が外部から見えないので使えない。
  • public クラスの internal メソッドは、クラスは見えるがメソッドにアクセスできない。
  • Windowsフォームアプリでは、プロジェクトごとに1つのアセンブリと考える。
  • InternalsVisibleTo を使うと、特定のアセンブリ間で internal を公開できる。

エラーが発生した場合は、クラスやメソッドのアクセス修飾子を見直し、適切な可視性を設定しましょう!