Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Тип List‹T›

Тип List‹T›

Подобно необобщенным классам, обобщенные классы являются объектами, размещаемыми в динамической памяти, поэтому для них следует использовать new со всеми необходимыми аргументами конструктора. Кроме того, вы должны указать типы, замещающие параметры, определенные обобщенным типом. Так, для System.Collections.Generic.List‹T› требуется указать одно значение, задающее вид элемента, с которым будет функционировать List‹T›. Например, чтобы создать три объекта List‹› для хранения целых чисел, объектов SportsCar и объектов Person, вы должны записать следующее

static void Main(string[] args) {
 // Создается List для хранения целых чисел.
 List‹int› myInts = new List‹int›();
 // Создается List для хранения объектов SportsCar.
 List‹SportsCar› myCars = new ListSportsCar›();
 // Создается List для хранения объектов Person.
 List‹Person› myPeople = new List‹Person›();
}

В этот момент вы можете поинтересоваться, что же на самом деле становится значением заполнителя. Открыв окно определения программного кода в Visual Studio 2005 (см. главу 2), вы увидите, что везде в определении типа List‹T› используется заполнитель Т. Ниже показана часть соответствующего листинга (обратите внимание на элементы, выделенные полужирным шрифтом).

// Часть листинга для типа List‹T›.
namespace System.Collections.Generic {
 public class List‹T›: IList‹T›, ICollection‹T›, IEnumerable‹T›, IList, ICollection, IEnumerable {
  …
  public void Add(T item);
  public IList‹T› AsReadOnly();
  public int BinarySearch(T item);
  public bool Contains(T item);
  public void CopyTo(T[] array);
  public int FindIndex(System.Predicate‹T› match);
  public T FindLast(System.Predicate‹T› match);
  public bool Remove(T item);
  public int RemoveAll(System.Predicate‹T› match);
  public T[] ToArray();
  public bool TrueForAll(System.Predicate‹T› match);
  public T this[int index] { get; set; }
  …
 }
}

Когда вы создаете тип List‹T› и указываете для него SportsCar, это эквивалентно следующему определению типа List‹T›.

namespace System.Collections.Generic {
 public class List‹SportsCar›: IList‹SportsCar›, ICollection‹SportsCar›, IEnumerable‹SportsCar›, IList, ICollection, IEnumerable {
  …
  public void Add(SportsCar item);
  public IList‹SportsCar› AsReadOnly();
  public int BinarySearch(SportsCar item);
  public bool Contains(SportsCar item);
  public void CopyTo(SportsCar[] array);
  public int FindIndex(System.Predicate‹SportsCar› match);
  public SportsCar FindLast(System.Predicate‹SportsCar› match);
  public bool Remove(SportsCar item);
  public int RemoveAll(System.Predicate‹SportsCar› match);
  publiс SportsCar[] ToArray();
  public bool TrueForAll(System.Predicate‹SportsCar› match);
  public SportsCar this[int index] { get; set; }
  …
 }
}

Конечно, когда вы создаете обобщенный List‹T›, нельзя сказать, что компилятор буквально создает совершенно новую реализацию типа List‹T›. Он обращается только к тем членам обобщенного типа, которые вы вызываете фактически. Чтобы пояснить это, предположим, что вы используете List‹T› для объектов SportsCar так.

static void Main(string[] args) {
 // Проверка List, содержащего объекты SportsCars.
 List‹SportsCar› myCars = new List‹SportsCar›();
 myCars.Add(new SportsCar());
 Console.WriteLine("Your List contains {0}", myCars.Count);
}

Если с помощью ildasm.exe проверить генерируемый CIL-код, обнаружатся следующие подстановки.

.method private hidebysig static void Main(string[] args) cil managed {
 .entrypoint
 .maxstack 2
 .locals init ([0] class [mscorlib] System.Collections.Generic.'List`1'‹class SportsCar› myCars)
 newobj instance void class [mscorlib]System.Collections.Generic.'List`1'‹class SportsCar›::.ctor()
 stloc.0
 ldloc.0
 newobj instance void CollectionGenerics.SportsCar::.ctor()
 callvirt instance void class [mscorlib]System.Collections.Generic.'List`1'‹class SportsCar›::Add(!0)
 nop
 ldstr "Your List contains {0} item(s)."
 ldloc.0
 callvirt instance int32 class [mscorlib] System.Collections.Generic.'List`1' ‹class SportsCar›::get_Count()
 box [mscorlib] System.Int32
 call void [mscorlib]System.Console::WriteLine(string, object)
 nop
 ret
}

Теперь, после изучения процесса использования обобщенных типов из библиотек базовых классов, в оставшейся части главы мы рассмотрим вопросы создания обобщенных методов, типов и коллекций.

Оглавление книги


Генерация: 5.852. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз