Упаковка и распаковка
Разберитесь в стоимости преобразования в 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 — локальная установка не требуется.
Все уроки этого курса
- Типы значений и ссылочные типы
- Упаковка и распаковка
- Неявные и явные преобразования
- Класс Convert и разбор значений