Первая проблема заключается в том, что использование классов коллекций System.Collections
System.Collections.Specialized в результате дает код с низкой производительностью, особенно в случае манипулирования числовыми данными (например, типами значений). Как вы вскоре увидите, когда структуры хранятся в любом необобщенном классе коллекции, прототипированном для оперирования с System.Object, среда CoreCLR должна осуществлять некоторое количество операций перемещения в памяти, что может нанести ущерб скорости выполнения.Вторая проблема связана с тем, что большинство необобщенных классов коллекций не являются безопасными в отношении типов, т.к. они были созданы для работы с System.Object
Прежде чем вы увидите, как применять обобщения в своих программах, полезно чуть глубже рассмотреть недостатки необобщенных классов коллекций, что поможет лучше понять проблемы, которые был призван решить механизм обобщений. Создайте новый проект консольного приложения по имени IssuesWithNongenericCollections
System и System.Collections в начале файла Program.cs и удалите оставшийся код:using System;
using System.Collections;
Проблема производительности
Как уже было указано в главе 4, платформа .NET Core поддерживает две обширные категории данных: типы значений и ссылочные типы. Поскольку в .NET Core определены две основные категории типов, временами возникает необходимость представить переменную одной категории как переменную другой категории. Для этого в C# предлагается простой механизм, называемый
SimpleBoxUnboxOperation() создана локальная переменная типа int. Если где-то в приложении понадобится представить такой тип значения как ссылочный тип, то значение придется static void SimpleBoxUnboxOperation()
{
// Создать переменную ValueType (int).
int myInt = 25;
// Упаковать int в ссылку на object.
object boxedInt = myInt;
}
Упаковку можно формально определить как процесс явного присваивания данных типа значения переменной System.Object
Противоположная операция также разрешена и называется
boxedInt действительно является int:static void SimpleBoxUnboxOperation()
{
// Создать переменную ValueType (int).
int myInt = 25;
// Упаковать int в ссылку на object.
object boxedInt = myInt;
// Распаковать ссылку обратно в int.
int unboxedInt = (int)boxedInt;
}
Когда компилятор C# встречает синтаксис упаковки/распаковки, он выпускает код CIL, который содержит коды операций box/unbox
ildasm.exe, то обнаружите в ней показанный далее код CIL:.method assembly hidebysig static
void '<
{
.maxstack 1
.locals init (int32 V_0, object V_1, int32 V_2)
IL_0000: nop
IL_0001: ldc.i4.s 25
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box [System.Runtime]System.Int32