web-dev-qa-db-ja.com

C#のプライベート内部クラス-なぜより頻繁に使用されないのですか?

私は比較的C#に慣れておらず、C#プロジェクトで作業を始めるたびに(C#ではほぼ成熟したプロジェクトでしか作業していませんでした)内部クラスがないのはなぜですか?

たぶん私は彼らの目標を理解していません。私にとって、内部クラス(少なくともプライベート内部クラス)は、Pascal/Modula-2/Adaの「内部手順」によく似ています。理解を容易にするために、メインクラスを小さな部分に分解できます。

例:ほとんどの場合、ここに表示されます:

public class ClassA
{
   public MethodA()
   {
      <some code>
      myObjectClassB.DoSomething(); // ClassB is only used by ClassA
      <some code>
   }
}

public class ClassB
{
   public DoSomething()
   {
   }
}

ClassBはClassAによってのみ(少なくともしばらく)使用されるため、このコードは次のように表現する方が良いと推測します。

   public class ClassA
   {
      public MethodA()
      {
         <some code>
         myObjectClassB.DoSomething(); // Class B is only usable by ClassA
         <some code>
      }

      private class ClassB
      {
         public DoSomething()
         {
         }
      }
   }

このテーマについてあなたから話を聞いてうれしいです-私は正しいですか?

74

ネストされたクラス(おそらく、C#のネストされたクラスはJavaの内部クラスとは異なるため、Wordの「内部」を避けるのが最善です)は、非常に便利です。

言及されていないパターンの1つに「より良い列挙」パターンがあります。これは、Javaのパターンよりもさらに柔軟です。

public abstract class MyCleverEnum
{
    public static readonly MyCleverEnum First = new FirstCleverEnum();
    public static readonly MyCleverEnum Second = new SecondCleverEnum();

    // Can only be called by this type *and nested types*
    private MyCleverEnum()
    {
    }

    public abstract void SomeMethod();
    public abstract void AnotherMethod();

    private class FirstCleverEnum : MyCleverEnum
    {
        public override void SomeMethod()
        {
             // First-specific behaviour here
        }

        public override void AnotherMethod()
        {
             // First-specific behaviour here
        }
    }

    private class SecondCleverEnum : MyCleverEnum
    {
        public override void SomeMethod()
        {
             // Second-specific behaviour here
        }

        public override void AnotherMethod()
        {
             // Second-specific behaviour here
        }
    }
}

いくつかの言語サポートでこれを自動的に行うことができます-すべての値にネストされたクラスを実際に使用しない、複数の値に同じネストされたクラスを使用するなど、ここには示していない多くのオプションがありますが、ただし、異なるコンストラクタパラメータを指定します。しかし、基本的に、ネストされたクラスがプライベートコンストラクターを呼び出すことができるという事実は、多くの力を与えます。

77
Jon Skeet

Framework Design Guidelines には、これまでに見つけたネストされたクラスを使用するための最良のルールがあります。

以下に簡単な要約リストを示します。

  1. 型とネストされた型との関係がメンバーアクセスのセマンティクスが望ましいようなものである場合は、ネストされた型を使用してください。

  2. 実行[〜#〜] not [〜#〜]ネストされたパブリック型を論理グループ構造として使用します

  3. 公開されているネストされた型の使用は避けてください。

  4. 型が包含型の外部で参照される可能性が高い場合は、ネストされた型を使用します[〜#〜] not [〜#〜]

  5. Do[〜#〜] not [〜#〜]クライアントコードでインスタンス化する必要がある場合は、ネストされた型を使用します。

  6. Do[〜#〜] not [〜#〜]は、ネストされたタイプをインターフェースのメンバーとして定義します。

29
matt_dev

各クラスの責任を制限して、各クラスがシンプル、テスト可能、再利用可能にとどまるようにしてください。プライベート内部クラスはそれに反します。それらは外部クラスの複雑さの一因となり、テストできず、再利用できません。

12
Wim Coenen

個人的には、メソッドを必要とするオブジェクトのインプロセスコレクションを作成する必要がある場合にのみ、プライベートな内部クラスを作成します。

そうしないと、プロジェクトに取り組んでいる他の開発者がこれらのクラスを実際に見つけるのに混乱が生じる可能性があります。

3
Tom Anderson