Частные внутренние классы в C # - почему они не используются чаще? - PullRequest
73 голосов
/ 18 января 2009

Я относительно новичок в 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()
         {
         }
      }
   }

Я был бы рад услышать от вас эту тему - я прав?

Ответы [ 4 ]

76 голосов
/ 18 января 2009

Вложенные классы (вероятно, лучше избегать слова «внутренний», поскольку вложенные классы в C # несколько отличаются от внутренних классов в Java) действительно могут быть очень полезны.

Один шаблон, который не был упомянут, - это шаблон "enum", который может быть даже более гибким, чем в 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
        }
    }
}

Мы могли бы сделать с некоторой языковой поддержкой, чтобы сделать это автоматически - и есть много опций, которые я здесь не показывал, например, не использовать вложенный класс для всех значений или использовать один и тот же вложенный класс для несколько значений, но давая им разные параметры конструктора. Но в основном тот факт, что вложенный класс может вызывать приватный конструктор, дает большую силу.

29 голосов
/ 12 ноября 2009

Руководство по разработке инфраструктуры содержит лучшие правила использования вложенных классов, которые я нашел на сегодняшний день.

Вот краткий сводный список:

  1. Используйте вложенные типы, когда связь между типом и вложенным типом такова, что желательна семантика доступности членов.

  2. Do НЕ использовать открытые вложенные типы в качестве логической конструкции группы

  3. Избегайте использования открытых вложенных типов.

  4. Do NOT использовать вложенные типы, если на тип, скорее всего, будут ссылаться за пределами содержащего типа.

  5. Делайте НЕ используйте вложенные типы, если их необходимо создать с помощью клиентского кода.

  6. Do NOT определяет вложенный тип как элемент интерфейса.

12 голосов
/ 18 января 2009

Вы должны ограничить обязанности каждого класса, чтобы каждый из них оставался простым, проверяемым и пригодным для повторного использования . Частные внутренние классы идут против этого. Они вносят вклад в сложность внешнего класса, они не поддаются тестированию и не могут использоваться повторно.

3 голосов
/ 18 января 2009

Лично для меня я создаю частные внутренние классы, только если мне нужно создавать внутрипроцессные коллекции объекта, для которых могут потребоваться методы.

В противном случае другие разработчики, работающие над проектом, могут запутаться в том, чтобы найти эти классы, поскольку они не очень ясно знают, где они находятся.

...