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

Проблемы создания объектных образов и строго типизованные коллекции

Проблемы создания объектных образов и строго типизованные коллекции

Строго типизованные коллекции можно найти в библиотеках базовых классов .NET и это очень полезные программные конструкции. Однако эти пользовательские контейнеры мало помотают в решении проблем создания объектных образов. Даже если вы создадите пользовательскую коллекцию с именем IntCollection, предназначенную для работы только с типами данных System.Int32, вам придется создать объект некоторого типа для хранения самих данных (System.Array, System.Collections.ArrayList и т.п.).

public class IntCollection: IEnumerable {
 private ArrayList arInts = new ArrayList();
 public IntCollection() {}
 // Восстановление значения для вызывающей стороны.
 public int GetInt(int pos) { return (int)arInts[pos]; }
 // Операция создания объектного образа!
 public void AddInt(int i) { arInts.Add(i); }
 public void ClearInts() { arInts.Clear(); }
 public int Count { get { return arInts.Count; } }
 IEnumerator IEnumerable.GetEnumerator() { return arInts.GetEnumerator(); }
}

Вне зависимости от того, какой тип вы выберете для хранения целых чисел (System.Array, System.Collections.ArrayList и т.п.), вы не сможете избавиться от проблемы .NET 1.1, связанной с созданием объектных образов. Нетрудно догадаться, что здесь снова на помощь приходят обобщения. В следующем фрагменте программного кода тип System.Collections.Generic.List‹› используется для создания контейнера целых чисел, не имеющего проблем создания объектных образов и восстановлений значений при вставке и получении типов характеризуемых значений.

static void Main (string [] args) {
 // Баз создания объектного образа!
 List‹int› myInts = new List‹int›();
 myInts.Add.(5);
 // Без восстановления значения!
 int i = myInts[0];
}

Просто в качестве подтверждения рассмотрите следующий CIL-код для этого метода Main() (обратите внимание да отсутствие в нем каких бы то ни было блоков box и unbox).

.method private hidebysig static void Main(string[] args) cil managed {
 .entrypoint
 // Code size 24 (0x18)
 .maxstack 2
 .locals init ([0] class [mscorlib] System.Collections.Generic.List`1‹int32› myInts, [1] int32 i)
 IL_0000: nop
 IL_0001: newobj instance void class [mscorlib] System.Collections.Generic.List`1‹int32›::.ctor()
 IL_0006: stloc.0
 IL_0007: ldloc.0
 IL_0008: ldc.i4.5
 IL_0009: callvirt instance void class [mscorlib]System.Collections.Generic.List`1‹int32›::Add(!0)
 IL_000e: nop
 IL_000f: ldloc.0
 IL_0010: ldc.i4.0
 IL_0011: callvirt instance !0 class [mscorlib]System.Collections.Generic.List`1‹int32›::get_Item(int32)
 IL_0016: stloc.1
 IL_0017: ret
} // end of method Program::Main

Теперь, когда вы имеете лучшее представление о роли обобщений в .NET2.0, мы с вами готовы углубиться в детали. Для начала мы формально рассмотрим пространство имен System.Collections.Generic.

Исходный код. Проект CustomNonGenericCollection размещен в подкаталоге, соответствующем главе 10.

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


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