Обобщенные классы, интерфейсы, структуры и делегаты вы можете обнаружить повсюду в библиотеках базовых классов .NET Core, и они могут быть частью любого пространства имен .NET Core. Кроме того, имейте в виду, что применение обобщений далеко не ограничивается простым определением класса коллекции. Разумеется, в оставшихся главах книги вы встретите случаи использования многих других обобщений для самых разных целей.
На заметку!
Обобщенным образом могут быть записаны только классы, структуры, интерфейсы и делегаты, но не перечисления.Глядя на обобщенный элемент в документации по .NET Core или в браузере объектов Visual Studio, вы заметите пару угловых скобок с буквой или другой лексемой внутри. На рис. 10.1 показано окно браузера объектов Visual Studio, в котором отображается набор обобщенных элементов из пространства имен System.Collections.Generic
List.Формально эти лексемы называются
<Т> можно читать как "типа Т". Таким образом, IEnumerable можно прочитать как "IEnumerable типа Т".На заметку!
Имя параметра типа (заполнитель) роли не играет и зависит от предпочтений разработчика, создавшего обобщенный элемент. Однако обычно имяT применяется для представления типов, ТКеу или К — для представления ключей и TValue или V — для представления значений.Когда вы создаете обобщенный объект, реализуете обобщенный интерфейс или вызываете обобщенный член, на вас возлагается обязанность по предоставлению значения для параметра типа. Многочисленные примеры вы увидите как в этой главе, так и в остальных материалах книги. Тем не менее, для начала рассмотрим основы взаимодействия с обобщенными типами и членами.
Указание параметров типа для обобщенных классов и структур
При создании экземпляра обобщенного класса или структуры вы указываете параметр типа, когда объявляете переменную и когда вызываете конструктор. Как было показано в предыдущем фрагменте кода, в методе UseGenericList()
List:// Этот объект List<> может хранить только объекты Person.
List
// Этот объект List<> может хранить только целые числа.
List
Первую строку приведенного выше кода можно трактовать как "список List<>
Т, где Т — тип Person" или более просто как "список объектов действующих лиц". После указания параметра типа обобщенного элемента изменить его нельзя (помните, что сущностью обобщений является безопасность в отношении типов). Когда параметр типа задается для обобщенного класса или структуры, все вхождения заполнителя (заполнителей) заменяются предоставленным значением.Если вы просмотрите полное объявление обобщенного класса List
Т используется в определении повсеместно. Ниже приведен частичный листинг:// Частичное определение класса List
namespace System.Collections.Generic
{
public class List
{
...
public void Add(T
public void AddRange(IEnumerable<T
public ReadOnlyCollection<T
public int BinarySearch(T
public bool Contains(T
public void CopyTo(T
public int FindIndex(System.Predicate<T
public T FindLast(System.Predicate<T
public bool Remove(T
public int RemoveAll(System.Predicate<T
public T
public bool TrueForAll(System.Predicate<T
public T
}
}
В случае создания List
Person результат будет таким же, как если бы тип List был определен следующим образом:namespace System.Collections.Generic
{
public class List<Person
: IList<Person
{
...
public void Add(Person
public void AddRange(IEnumerable<Person