Почему я должен был бы когда-либо использовать C# вложенные классы [дубликат]

Существует простая причина этого в том, что объект не обязан вызывать статический метод. Если это был нестатический метод, виртуальная машина Java сначала создает объект, а затем вызывает метод main (), что приведет к проблеме дополнительных распределение памяти.

214
задан yas4891 24 September 2011 в 23:23
поделиться

7 ответов

Обычно цель состоит в том, чтобы ограничить область вложенного класса. Вложенные классы по сравнению с обычными классами имеют дополнительную возможность модификатора private (а также, конечно, protected ).

В принципе, если вам нужно использовать этот класс только изнутри "родительский" класс (с точки зрения области видимости), то обычно целесообразно определить его как вложенный класс. Если этот класс может потребоваться из без сборки / библиотеки , тогда пользователю обычно удобнее определить его как отдельный (родственный) класс, независимо от того, существует ли концептуальная связь между два класса. Хотя технически возможно создать общедоступный класс, вложенный в общедоступный родительский класс,

114
ответ дан 23 November 2019 в 04:23
поделиться

Шаблон, который мне особенно нравится, - это комбинирование вложенных классов с шаблоном фабрики:

public abstract class BankAccount
{
  private BankAccount() {} // prevent third-party subclassing.
  private sealed class SavingsAccount : BankAccount { ... }
  private sealed class ChequingAccount : BankAccount { ... }
  public static BankAccount MakeSavingAccount() { ... }
  public static BankAccount MakeChequingAccount() { ... }
}

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

263
ответ дан 23 November 2019 в 04:23
поделиться

Вложенный класс может иметь модификаторы доступа private , protected и protected internal вместе с public и внутренний .

Например, вы реализуете метод GetEnumerator () , который возвращает объект IEnumerator . Потребители не заботятся о фактическом типе объекта. Все, что они знают об этом, - это то, что он реализует этот интерфейс. Класс, который вы хотите вернуть, не имеет прямого использования. Вы можете объявить этот класс как частный вложенный класс и вернуть его экземпляр (именно так компилятор C # реализует итераторы):

class MyUselessList : IEnumerable<int> {
    // ...
    private List<int> internalList;
    private class UselessListEnumerator : IEnumerator<int> {
        private MyUselessList obj;
        public UselessListEnumerator(MyUselessList o) {
           obj = o;
        }
        private int currentIndex = -1;
        public int Current {
           get { return obj.internalList[currentIndex]; }
        }
        public bool MoveNext() { 
           return ++currentIndex < obj.internalList.Count;
        }
    }
    public IEnumerator<int> GetEnumerator() {
        return new UselessListEnumerator(this);
    }
}
51
ответ дан 23 November 2019 в 04:23
поделиться

чего я не понимаю, так это того, почему мне когда-нибудь понадобится это сделать

Я думаю, вам никогда не понадобится этого. Учитывая вложенный класс, подобный этому ...

class A
{
  //B is used to help implement A
  class B
  {
    ...etc...
  }
  ...etc...
}

... вы всегда можете переместить внутренний / вложенный класс в глобальную область видимости, как этот ...

class A
{
  ...etc...
}

//B is used to help implement A
class B
{
  ...etc...
}

Однако, когда B используется только для помощи в реализации A, тогда создание B внутренний / вложенный класс имеет два преимущества:

  • Он не загрязняет глобальную область видимости (например, клиентский код, который видит A, не знает, что класс B вообще существует)
  • Методы B неявно имеют доступ частным членам A; тогда как, если бы B не был вложен в A, B не смог бы получить доступ к членам A, если бы эти члены не были внутренними или общедоступными; но затем, если сделать эти члены внутренними или общедоступными, они будут открыты и для других классов (не только для B); поэтому вместо этого оставьте эти методы A закрытыми и позвольте B получить к ним доступ, объявив B как вложенный класс. Если вы знакомы с C ++, это все равно, что сказать, что в C # все вложенные классы автоматически становятся « другом » класса, в котором они содержатся (и что объявление класса как вложенного - единственный способ объявить дружбу на C #, поскольку C # не имеет друга ключевое слово).

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

оставьте эти методы класса A закрытыми и позвольте B получить к ним доступ, объявив B как вложенный класс. Если вы знакомы с C ++, это все равно, что сказать, что в C # все вложенные классы автоматически становятся « другом » класса, в котором они содержатся (и что объявление класса как вложенного - единственный способ объявить дружбу на C #, поскольку C # не имеет друга ключевое слово).

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

оставьте эти методы класса A закрытыми и позвольте B получить к ним доступ, объявив B как вложенный класс. Если вы знакомы с C ++, это все равно, что сказать, что в C # все вложенные классы автоматически становятся « другом » класса, в котором они содержатся (и что объявление класса как вложенного - единственный способ объявить дружбу на C #, поскольку C # не имеет друга ключевое слово).

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

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

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

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

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

Когда я говорю, что B может получить доступ к закрытым членам A, это предполагает, что B имеет ссылку на A; что часто бывает, так как вложенные классы часто объявляются вот так ...

class A
{
  //used to help implement A
  class B
  {
    A m_a;
    internal B(A a) { m_a = a; }
    ...methods of B can access private members of the m_a instance...
  }
  ...etc...
}

... и создаются из метода A с использованием такого кода ...

//create an instance of B, whose implementation can access members of self
B b = new B(this);

Вы можете увидеть пример в ответе Мехрдада.

45
ответ дан 23 November 2019 в 04:23
поделиться

Также есть хорошее применение публичных вложенных членов ...

Вложенные классы имеют доступ к закрытым членам внешнего класса. Таким образом, сценарий, в котором это правильный путь, будет при создании Comparer (т. Е. Реализации интерфейса IComparer).

В этом примере FirstNameComparer имеет доступ к частному члену _firstName, чего не было бы, если бы класс был отдельный класс ...

public class Person
{
    private string _firstName;
    private string _lastName;
    private DateTime _birthday;

    //...

    public class FirstNameComparer : IComparer<Person>
    {
        public int Compare(Person x, Person y)
        {
            return x._firstName.CompareTo(y._lastName);
        }
    }

}
30
ответ дан 23 November 2019 в 04:23
поделиться

Бывают моменты когда это' полезно для реализации интерфейса, который будет возвращен из класса, но реализация этого интерфейса должна быть полностью скрыта от внешнего мира.

В качестве примера - до добавления yield в C # был один способ реализации Перечислители должны были поместить реализацию перечислителя как частный класс в коллекцию. Это обеспечило бы легкий доступ к членам коллекции, но внешнему миру не нужно было бы видеть детали того, как это реализовано.

18
ответ дан 23 November 2019 в 04:23
поделиться

Вложенные классы очень полезны для реализации внутренних деталей, которые не следует раскрывать. Если вы используете Reflector для проверки таких классов, как Dictionary или Hashtable, вы найдете несколько примеров.

5
ответ дан 23 November 2019 в 04:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: