Шрифт:
Интервал:
Закладка:
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>(). Рассмотрим представленный далее фрагмент кода, где Т — тип int:
int[] 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. Вспомните, что необобщенный интерфейс IComparable определен примерно так:
public interface IComparable
{
int CompareTo(object obj);
}
В главе 8 этот интерфейс также был реализован классом Car, чтобы сделать возможной сортировку стандартного массива. Однако код требовал нескольких проверок времени выполнения и операций приведения, потому что параметром был общий тип System.Object:
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})public 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 для многих из них определены обобщенные замены.
- Понимание SQL - Мартин Грубер - Базы данных