public ReadOnlyCollection<Person> AsReadOnly();

    public int BinarySearch(Person item);

    public bool Contains(Person item);

    public void CopyTo(Person[] array);

    public int FindIndex(System.Predicate<Person> match);

    public Person FindLast(System.Predicate<Person> match);

    public bool Remove(Person item);

    public int RemoveAll(System.Predicate<Person> match);

    public Person[] ToArray();

    public bool TrueForAll(System.Predicate<Person> match);

    public Person this[int index] { get; set; }

  }

}

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

<p id="AutBody_Root383">Указание параметров типа для обобщенных членов</p>

В необобщенном классе или структуре разрешено поддерживать обобщенные свойства. В таких случаях необходимо также указывать значение заполнителя во время вызова метода. Например, класс System.Array поддерживает набор обобщенных методов. В частности, необобщенный статический метод Sort() имеет обобщенный аналог по имени Sort(). Рассмотрим представленный далее фрагмент кода, где Т — тип int:

int[] myInts = { 10, 4, 2, 33, 93 };

// Указание заполнителя для обобщенного метода Sort<>().

Array.Sort(myInts);

foreach (int i in myInts)

{

  Console.WriteLine(i);

}

<p id="AutBody_Root384">Указание параметров типов для обобщенных интерфейсов</p>

Обобщенные интерфейсы обычно реализуются при построении классов или структур,которые нуждаются в поддержке разнообразных аспектов поведения платформы (скажем, клонирования, сортировки и перечисления). В главе 8 вы узнали о нескольких необобщенных интерфейсах, таких как IComparable, IEnumerable, IEnumerator и IComparer. Вспомните, что необобщенный интерфейс IComparable определен примерно так:

public interface IComparable

{

  int CompareTo(object obj);

}

В главе 8 этот интерфейс также был реализован классом Car, чтобы сделать возможной сортировку стандартного массива. Однако код требовал нескольких проверок времени выполнения и операций приведения, потому что параметром был общий тип System.Object:

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

{

  int CompareTo(T obj);

}

В таком случае код реализации будет значительно яснее:

public class Car : IComparable

{

  ...

  // Реализация IComparable.

  int IComparable.CompareTo(Car obj)

  {

    if (this.CarID > obj.CarID)

    {

      return 1;

    }

 if (this.CarID < obj.CarID)

    {

      return -1;

    }

    return 0;

  }

}

Здесь уже не нужно проверять, относится ли входной параметр к типу Car, потому что он может быть только Car! В случае передачи несовместимого типа данных возникает ошибка на этапе компиляции. Теперь, углубив понимание того, как взаимодействовать с обобщенными элементами, а также усвоив роль параметров типа (т.е. заполнителей), вы готовы к исследованию классов и интерфейсов из пространства имен System.Collections.Generic.

<p id="AutBody_Root385">Пространство имен System.Collections.Generic</p>
Перейти на страницу:

Похожие книги