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
}
Теперь, после изучения процесса использования обобщенных типов из библиотек базовых классов, в оставшейся части главы мы рассмотрим вопросы создания обобщенных методов, типов и коллекций.
Создание обобщенных методов
Чтобы научиться интегрировать обобщения в проекты, мы начнем с простого примера обычной подпрограммы свопинга. Целью этого примера является построение метода обмена, который сможет работать c любыми типами данных (характеризуемыми значениями или ссылками), используя для этого один параметр типа. В силу самой природы алгоритмов свопинга входные параметры будут посылаться по ссылке (с помощью ключевого слова C# ref). Вот соответствующая полная реализация.
// Этот метод переставляет любые два элемента,
// определенные параметром типа ‹Т›.
static void Swap‹T›(ref T a, ref Т b) {
Console.WriteLine ("Методу Swap передано {0}", typeof(T));
Т temp;
temp = а;
а = b;