0Pricing
C# Academy · Урок

Упаковка и распаковка

Разберитесь в стоимости преобразования в object.

«Упаковка и распаковка» — бесплатный урок C# Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Что такое упаковка

Упаковка помещает тип значения внутрь объекта, чтобы с ним можно было обращаться как со ссылочным типом. object o = 5; упаковывает значение int в куче.

using System;

class Program
{
    static void Main()
    {
        int n = 5;
        object o = n;   // boxing
        Console.WriteLine("Boxed value: " + o);
    }
}

Почему происходит упаковка

Упаковка происходит всякий раз, когда тип значения присваивается переменной типа object (или интерфейса). Среда выполнения выделяет в куче контейнер, содержащий копию значения.

using System;

class Program
{
    static void Main()
    {
        double d = 3.14;
        object boxed = d;   // boxing copies d into a heap object
        Console.WriteLine(boxed);
    }
}

Что такое распаковка

Распаковка извлекает тип значения из контейнера с помощью явного приведения. Тип приведения должен в точности совпадать с типом, который был упакован.

using System;

class Program
{
    static void Main()
    {
        object o = 42;        // boxing
        int n = (int)o;        // unboxing
        Console.WriteLine("Unboxed: " + n);
    }
}

Для распаковки нужен правильный тип

Распаковывать значение необходимо в его исходный тип. Распаковка в другой тип вызывает исключение InvalidCastException.

using System;

class Program
{
    static void Main()
    {
        object o = 100;
        try
        {
            long wrong = (long)o;   // InvalidCastException at runtime
            Console.WriteLine(wrong);
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Must unbox to int, not long");
        }
    }
}

Упаковка создаёт копию

При упаковке значение копируется. Последующее изменение исходного значения не изменяет упакованную копию.

using System;

class Program
{
    static void Main()
    {
        int n = 1;
        object o = n;   // box copies 1
        n = 99;
        Console.WriteLine("original=" + n + ", boxed=" + o);
    }
}

Цена упаковки

Каждая упаковка выделяет память в куче и увеличивает нагрузку на сборщик мусора. В часто выполняемых циклах эти накладные расходы могут значительно снизить производительность.

using System;

class Program
{
    static void Main()
    {
        // Each iteration boxes an int -> many heap allocations
        object sumBox = 0;
        for (int i = 0; i < 5; i++)
        {
            int current = (int)sumBox + i;
            sumBox = current;   // box again
        }
        Console.WriteLine("Result: " + sumBox);
    }
}

Как избежать упаковки с помощью обобщений

Обобщённые коллекции, например List<int>, хранят типы значений без упаковки, в отличие от старой коллекции без обобщений ArrayList.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var list = new List<int>();   // no boxing
        list.Add(1);
        list.Add(2);
        int first = list[0];           // no unboxing
        Console.WriteLine("First: " + first);
    }
}

Упаковка при работе с интерфейсами

Присваивание структуры переменной типа интерфейса также упаковывает её, поскольку ссылка на интерфейс должна указывать на объект в куче.

using System;

class Program
{
    static void Main()
    {
        int n = 7;
        IComparable c = n;   // boxing to interface
        Console.WriteLine(c.CompareTo(10));
    }
}

Определение упакованных типов

Во время выполнения можно проверить тип упакованного объекта с помощью is, прежде чем безопасно распаковывать его.

using System;

class Program
{
    static void Main()
    {
        object o = 3.5;
        if (o is double d)
            Console.WriteLine("It is a double: " + d);
        else
            Console.WriteLine("Not a double");
    }
}

Упаковка при объединении строк

Объединение типа значения со строками может привести к его упаковке. Интерполяция или ToString часто понятнее, хотя в данном случае упаковка обычно почти не влияет на производительность.

using System;

class Program
{
    static void Main()
    {
        int count = 3;
        string msg = "Count is " + count;   // count is converted
        Console.WriteLine(msg);
    }
}

Объединяем всё вместе

Упаковка связывает мир типов значений с миром ссылочных типов, но требует выделения памяти. Предпочитайте обобщения, чтобы избежать упаковки, и распаковывайте значения только в точно соответствующий тип после безопасной проверки.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        object boxed = 256;
        if (boxed is int value)
            Console.WriteLine("Safely unboxed: " + value);

        var noBox = new List<int> { 1, 2, 3 };
        Console.WriteLine("Generic count: " + noBox.Count);
    }
}

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете упаковку и распаковку.

Повторение

Упаковка помещает тип значения в объект в куче (например, object o = 5;); распаковка извлекает его с помощью явного приведения к исходному типу. Упаковка копирует значение и выделяет память, увеличивая нагрузку на сборщик мусора. Предпочитайте обобщённые коллекции, например List<int>, чтобы избежать упаковки, и используйте is для безопасной распаковки.

using System;

class Program
{
    static void Main()
    {
        object boxed = 42;     // box
        int n = (int)boxed;     // unbox
        Console.WriteLine(n);
    }
}

Часто задаваемые вопросы

Урок «Упаковка и распаковка» бесплатный?

Да — полный текст урока «Упаковка и распаковка» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Упаковка и распаковка»?

Разберитесь в стоимости преобразования в object. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Упаковка и распаковка»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Типы значений и ссылочные типы
  2. Упаковка и распаковка
  3. Неявные и явные преобразования
  4. Класс Convert и разбор значений
← Назад к C# Academy