Язык программирования C#9 и платформа .NET5
public int BinarySearch(<b>Person</b> item);public bool Contains(<b>Person</b> item);public void CopyTo(<b>Person</b>[] array);public int FindIndex(System.Predicate<<b>Person</b>> match);public Person FindLast(System.Predicate<<b>Person</b>> match);public bool Remove(<b>Person</b> item);public int RemoveAll(System.Predicate<<b>Person</b>> match);public <b>Person</b>[] ToArray();public bool TrueForAll(System.Predicate<<b>Person</b>> match);public <b>Person</b> this[int index] { get; set; }}}Несомненно, когда вы создаете в коде переменную обобщенного типа
, компилятор вовсе не создает новую реализацию классаList<T>. Взамен он принимает во внимание только члены обобщенного типа, к которым вы действительно обращаетесь.List<T>Указание параметров типа для обобщенных членов
В необобщенном классе или структуре разрешено поддерживать обобщенные свойства. В таких случаях необходимо также указывать значение заполнителя во время вызова метода. Например, класс
поддерживает набор обобщенных методов. В частности, необобщенный статический методSystem.Arrayимеет обобщенный аналог по имениSort(). Рассмотрим представленный далее фрагмент кода, гдеSort<T>()— типТ:intint[] myInts = { 10, 4, 2, 33, 93 };<b>// Указание заполнителя для обобщенного метода Sort<>().</b>Array.Sort<int>(myInts);foreach (int i in myInts){Console.WriteLine(i);}Указание параметров типов для обобщенных интерфейсов
Обобщенные интерфейсы обычно реализуются при построении классов или структур,которые нуждаются в поддержке разнообразных аспектов поведения платформы (скажем, клонирования, сортировки и перечисления). В главе 8 вы узнали о нескольких необобщенных интерфейсах, таких как
,IComparable,IEnumerableиIEnumerator. Вспомните, что необобщенный интерфейсIComparerопределен примерно так:IComparablepublic interface IComparable{int CompareTo(object obj);}В главе 8 этот интерфейс также был реализован классом
, чтобы сделать возможной сортировку стандартного массива. Однако код требовал нескольких проверок времени выполнения и операций приведения, потому что параметром был общий типCar:System.Objectpublic class Car : IComparable{...// Реализация IComparable.int IComparable.CompareTo(object obj){if (obj is Car temp){return this.CarID.CompareTo(temp.CarID);}throw new ArgumentException("Parameter is not a Car!");// Параметр не является объектом типа Car!}}Теперь представим, что применяется обобщенный аналог данного интерфейса:
public interface IComparable<T>{int CompareTo(T obj);}В таком случае код реализации будет значительно яснее:
public class Car : IComparable<Car>{...// Реализация IComparable<T>.int IComparable<Car>.CompareTo(Car obj){if (this.CarID > obj.CarID){return 1;}if (this.CarID < obj.CarID){return -1;}return 0;}}Здесь уже не нужно проверять, относится ли входной параметр к типу
, потому что он может быть толькоCar! В случае передачи несовместимого типа данных возникает ошибка на этапе компиляции. Теперь, углубив понимание того, как взаимодействовать с обобщенными элементами, а также усвоив роль параметров типа (т.е. заполнителей), вы готовы к исследованию классов и интерфейсов из пространства именCar.System.Collections.GenericПространство имен System.Collections.Generic
Когда вы строите приложение .NET Core и необходим способ управления данными в памяти, классы из пространства имен
вероятно удовлетворят всем требованиям. В начале настоящей главы кратко упоминались некоторые основные необобщенные интерфейсы, реализуемые необобщенными классами коллекций. Не должен вызывать удивление тот факт, что в пространстве именSystem.Collections.Genericдля многих из них определены обобщенные замены.System.Collections.Generic