Главная arrow Язык программирования C# arrow C# Полное руководство Герберт Шилдт arrow Упаковка и распаковка C# Полное руководство Герберт Шилдт

Упаковка и распаковка C# Полное руководство Герберт Шилдт

Как пояснялось выше, все типы в С#, включая и простые типы значений, являются производными от класса object. Следовательно, ссылкой типа object можно воспользоваться для обращения к любому другому типу, в том числе и к типам значений. Когда ссылка на объект класса object используется для обращения к типу значения, то такой процесс называется упаковкой. Упаковка приводит к тому, что значение простого типа сохраняется в экземпляре объекта, т.е. “упаковывается” в объекте, который затем используется как и любой другой объект. Но в любом случае упаковка происходит автоматически. Для этого достаточно присвоить значение переменной ссылочного типа object, а об остальном позаботится компилятор С#.
Распаковка представляет собой процесс извлечения упакованного значения из объекта. Это делается с помощью явного приведения типа ссылки на объект класса object к соответствующему типу значения. Попытка распаковать объект в другой тип может привести к ошибке во время выполнения.
Ниже приведен простой пример, демонстрирующий упаковку и распаковку.

// Простой пример упаковки и распаковки.

using System;

class BoxingDemo {
   static void Main() {
      int x;
      object obj;

      x = 10;
      obj = x; // упаковать значение переменной x в объект

      int у = (int)obj; // распаковать значение из
                                // объекта, доступного по ссылке obj,
                                //в переменную типа int
      Console.WriteLine (у) ;
   }
}


В этом примере кода выводится значение 10. Обратите внимание на то, что значение переменной х упаковывается в объект простым его присваиванием переменной obj, ссылающейся на этот объект. А затем это значение извлекается из объекта, доступного по его ссылке obj, и далее приводится к типу int.
Ниже приведен еще один интересный пример упаковки. В данном случае значение типа int передается в качестве аргумента методу Sqr (), который, в свою очередь, принимает параметр типа object.

// Пример упаковки при передаче значения методу.

using System;

class BoxingDemo {
   static void Main() {
      int x;
      x = 10;

      Console.WriteLine("Значение x равно: " + x) ;

      // значение переменной x автоматически упаковывается
      // когда оно передается методу Sqr().
      х = BoxingDemo.Sqr(х);
      Console.WriteLine("Значение x в квадрате равно: " + х) ;
   }

   static int Sqr(object о) {
      return (int)о * (int)о;
   }
}


Вот к какому результату приводит выполнение этого кода:
   Значение х равно: 10
   Значение х в квадрате равно: 100

В данном примере значение переменной х автоматически упаковывается при передаче методу Sqr ().
Упаковка и распаковка позволяют полностью унифицировать систему типов в С#. Благодаря тому что все типы являются производными от класса object, ссылка на значение любого типа может быть просто присвоена переменной ссылочного типа object, а все остальное возьмут на себя упаковка и распаковка. Более того, методы класса object оказываются доступными всем типам, поскольку они являются производными от этого класса. В качестве примера рассмотрим довольно любопытную программу:

// Благодаря упаковке становится возможным вызов методов-по значению!

using System;

class MethOnValue {
   static void Main() {
      Console.WriteLine(10.ToString());
   }
}


В результате выполнения этой программы выводится значение 10. Дело в том, что метод ToString () возвращает строковое представление объекта, для которого он вызывается. В данном случае строковым представлением значения 10 как вызывающего объекта является само значение 10!