Интересные моменты в C# (boxing unboxing)

В этой статье мы коротко пройдемся по малоизвестным особенностям boxing/unboxing.Предыдущая статья о foreachПредыдущая статья об Array

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

Тестовый код:

object box = (int)42; long unbox = (long)box; Ответ может быть следующий — «При распаковке первый оператор является не приведением типов, а распаковкой типа, соответственно он должен соответствовать типу значения находящегося в запакованном виде.».Правильный ответ:

object box = (int)42; long unbox = (long)(int)box; Обычно это считается правильным ответом, но это не совсем так…Unboxing и Enum Представьте себе удивление человека, когда вы ему напишете другой правильный вариант.Второй правильный ответ:

public enum EnumType { None } … object box = (int)42; long unbox = (long)(EnumType)box; Напомню, enum не является фундаментальным типом и не наследует его, он является структурой содержащей фундаментальный тип (базовый). Это говорит о том что в .NET есть явная поддержка такой распаковки. Так же легко проверить что распаковка не использует операторы явного и неявного преобразования и интерфейс IConvertible и свой тип не получится развернуть из чужого типа.При распаковке enum’а используется его базовый тип и следующая распаковка не будет работать.Неправильный вариант:

public enum EnumType: short { None } … object box = (int)42; long unbox = (long)(EnumType)box; Распаковка для enum’ов ослаблена предельно.Распаковываем int из enum’а:

public enum EnumType { None } … object box = EnumType.None; long unbox = (long)(int)box; Распаковываем один enum из другого: public enum EnumType { None } public enum EnumType2 { None } … object box = EnumType.None; long unbox = (long)(EnumType2)box; Unboxing и Nullable Распаковка поддерживает и Nullable типы, что кажется более логичным.Распаковка Nullable типа из обычного:

object box = (int)42; long unbox = (long)(int?)box; Распаковка обычного типа из Nullable: object box = (int?)42; long unbox = (long)(int)box; Напомню что Nullable это структура с одним обобщенным типом значения и предназначена для хранения данных и флага присутствия данных. Это говорит о том что в C# есть явная поддержка распаковки Nullable типов. В новых версиях C# для этой структуры появился alias »?».Nullable:

public struct Nullable where T: struct { public bool HasValue { get; } public T Value { get; } } Равнозначные записи: Nullable value; int? value; Всем спасибо за внимание!

© Habrahabr.ru