Подтвердить что ты не робот

Generics -Открытые и закрытые построенные типы

Недавно я заметил, что общие построенные типы могут быть открытыми и закрытыми. Но я не понимаю, что они на самом деле означают. Можете ли вы привести простой пример?

4b9b3361

Ответ 1

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

  • Несвязанный тип не имеет указанных аргументов типа
  • В построенном типе указан хотя бы один аргумент типа
  • Параметр типа является открытым типом
  • Тип массива, в котором тип элемента открыт, является открытым типом
  • Открытый построенный тип имеет хотя бы один аргумент типа, который является открытым типом
  • Закрытый тип - это любой тип, который не открыт

(Для вложенных типов существуют дополнительные правила. Обратитесь к разделу 4.4 спецификаций С# 3.0 для подробных сведений.)

В качестве примера открытого построенного типа рассмотрим:

public class NameDictionary<T> : Dictionary<string, T>

Базовый класс typeof(NameDictionary<>):

  • Построено, поскольку оно задает аргументы типа
  • Открыть, потому что аргумент второго типа (T) является открытым типом

Документы MSDN для Type.IsGenericType имеют довольно полезную небольшую таблицу.

Чтобы повторить, это почти совсем не важно в повседневном использовании.

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

Ответ 2

От MSDN:

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

Итак, это работает как List<int> закрыто:

var list = Activator.CreateInstance(typeof(List<int>));

Но это вызывает исключение во время выполнения, потому что List<> open:

var list = Activator.CreateInstance(typeof(List<>));
                                               ↑

Ответ 3

В основном я использовал открытые дженерики (в основном, необоснованные дженерики) в сопоставлениях инъекций зависимостей. Например, что-то вроде

Bind<IRepository<>>()
   .To<BasicRepository<>>()

Затем, когда мой конструктор объектов содержит:

public SomethingController(IRepository<Something>) { ... }

Мой механизм инъекции зависимостей будет создавать экземпляр BasicRepository < Что-то > автоматически. (Это работает с Ninject и StructureMap и, возможно, с библиотекой Castle Windsor, я не уверен в других фреймворках).