Boxing — это процесс преобразования value type (типа значения) в reference type (ссылочный тип), а именно в object
или в любой интерфейс, который реализует этот value type.
int number = 42; // value type в стеке
object boxed = number; // boxing: число копируется в кучу
Unboxing — это обратный процесс извлечения value type из упакованного объекта.
object boxed = 42; // Упакованное число
int unboxed = (int)boxed; // Unboxing
InvalidCastException
object boxed = 42;
long unboxed = (long)boxed; // Ошибка времени выполнения!
void Print(object obj) { /* ... */ }
int number = 10;
Print(number); // Происходит boxing
IFormattable formattable = 42; // Boxing происходит здесь
int i = 10;
object o1 = i; // Boxing 1
object o2 = i; // Boxing 2 - создается ДРУГОЙ объект
Boxing/unboxing имеют накладные расходы:
Пример с коллекциями:
ArrayList list = new ArrayList(); // Не generic-коллекция
for (int i = 0; i < 100000; i++) {
list.Add(i); // Boxing на каждой итерации!
}
Использовать generic-коллекции:
List<int> list = new List<int>(); // Нет boxing'а
Использовать обобщенные методы:
void Print<T>(T value) where T : struct { /* ... */ }
Print(42); // Нет boxing'а
Использовать специальные интерфейсы:
Для числовых типов можно использовать INumber<T>
int? nullableInt = 42;
object boxed = nullableInt; // Boxing nullable типа
object boxed = 42;
int? unboxed = (int?)boxed; // Корректно
enum Color { Red, Green }
object boxed = Color.Red; // Boxing enum
Boxing и unboxing — это механизмы преобразования между value types и reference types, которые влияют на производительность. Boxing копирует значение в кучу, создавая объект, а unboxing извлекает значение обратно. Важно минимизировать эти операции, используя generics и понимая их скрытые проявления в коде.