Что такое boxing и unboxing в C#

Boxing и Unboxing — это механизмы преобразования значимых типов в ссылочные и обратно. Они позволяют работать с универсальными коллекциями, интерфейсами и объектами общего назначения, но их частое использование может привести к снижению производительности из-за дополнительных операций в куче (heap).

Что такое boxing

Boxing — это процесс преобразования значимого типа (value type) в ссылочный (reference type).

Пример boxing

using System;

class Program
{
    static void Main()
    {
        int value = 10;
        object boxedValue = value; // Упаковка (boxing)
        Console.WriteLine(boxedValue);
    }
}

В этом примере value является значимым типом (int). При присвоении переменной boxedValue он автоматически преобразуется в object, создавая новую копию в управляемой куче (heap).

Что такое unboxing

Unboxing — это процесс извлечения значимого типа из ссылочного.

Пример unboxing

using System;

class Program
{
    static void Main()
    {
        object boxedValue = 10; // Упаковка
        int value = (int)boxedValue; // Распаковка (unboxing)
        Console.WriteLine(value);
    }
}

В этом примере boxedValue содержит значение типа int, но для использования его как int, необходимо явное приведение ((int)boxedValue).

Основные различия между boxing и unboxing

ХарактеристикаBoxingUnboxing
ОперацияПреобразование значимого типа в ссылочныйПреобразование ссылочного типа обратно в значимый
ПроизводительностьСоздает объект в куче, затратно по памятиМожет вызывать дополнительные расходы, если выполняется часто
Требует явного приведенияНетДа

Как избежать издержек от boxing и unboxing

  • Использовать обобщения (Generics), так как они работают с конкретными типами без преобразований.
  • Использовать struct только в случаях, когда упаковка в object не требуется.
  • Использовать коллекции List<T>, Dictionary<TKey, TValue> вместо ArrayList и Hashtable.

Пример с использованием Generics

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int>(); // Без упаковки
        numbers.Add(10);
        int value = numbers[0];
        Console.WriteLine(value);
    }
}

Boxing и Unboxing могут вызывать накладные расходы в работе приложения, поэтому рекомендуется минимизировать их использование с помощью обобщений и современных коллекций.