Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Примеры создания объектных образов и восстановления значений

Примеры создания объектных образов и восстановления значений

Вы, наверное, спросите, когда действительно бывает необходимо вручную выполнять преобразование в объектный тип (или восстановление из объектного образа)? Предыдущий пример был исключительно иллюстративным, поскольку в нем для данных short не было никакой реальной необходимости приведении к объектному типу (с последующим восстановлением данных из объектного образа).

Реальность такова, что необходимость вручную приводить данные к объектному типу возникает очень редко – если возникает вообще. В большинстве случаев компилятор C# выполняет такие преобразования автоматически. Например, при передаче типа, характеризуемого значением, методу, предполагающему получение объектного параметра, автоматически "в фоновом режиме" происходит приведение к объектному типу.

class Program {
 static void Main(string[] args) {
 // Создание значения int (тип, характеризуемый значением).
 int myInt = 99;
 // myInt передается методу, предполагающему
 // получение объекта, поэтому myInt приводится
 // к объектному типу автоматически.
 UseThisObject(myInt);
 Console.ReadLine();
}
static void UseThisObject(object o) {
 Console.WriteLine("Значением о является: {0}", о);}
}

Автоматическое преобразование в объектный тип происходит и при работе c типами библиотек базовых классов .NET. Например, пространство имен System.Collections (формально оно будет обсуждаться в главе 7) определяет тип класса с именем ArrayList. Подобно большинству других типов коллекций, ArrayList имеет члены, позволяющие вставлять, получать и удалять элементы.

public class System.Collections.ArrayList: object, System.Collections.IList, System.Collections.ICollection, System.Collections.IEnumerable, ICloneable {
 …
 public virtual int Add(object value);
 public virtual void Insert(int index, object value);
 public virtual void Remove(object obj);
 public virtual object this[int index] {get; set;}
}

Как видите, эти члены действуют на типы System.Object. Поскольку все, в конечном счете, получается из этого общего базового класса, следующий программный код оказывается вполне корректным.

static void Main(string [] args) {
 …
 ArrayList myInts = new ArrayList();
 myInts.Add(88);
 myInts.Add(3.33);
 myInts.Add(false);
}

Но теперь с учетом вашего понимания ссылочных типов и типов, характеризуемые значением, вы можете спросить: что же на самом деле размещается в ArrayList? (Ссылки? Копии ссылок? Копии структур?) Как и в случае, с рассмотренным выше методом UseThisObject(), должно быть ясно, что каждый из типов данных System.Int32 перед размещением в ArrayList в действительности приводится к объектному типу. Чтобы восстановить элемент из типа ArrayList, требуется выполнить соответствующую операцию восстановления.

static void BoxAndUnboxInts() {
 // "Упаковка" данных int в ArrayList.
 ArrayList myInts = new ArrayList();
 myInts.Add(88);
 myInts.Add(3.33);
 myInts.Add(false);
 // Извлечение первого элемента из ArrayList.
 int firstItem = (int)myInts[0];
 Console.WriteLine("Первым элементом является {0}", firstItem);
}

Без сомнения, операции приведения к объектному типу и восстановления из объектного образа требуют времени и, если эти операций использовать без ограничений, это может влиять на производительность приложения. Но с использованием такого подхода .NET вы можете симметрично работать с типами характеризуемыми значением, и со ссылочными типами.

Замечание. В C# 2.0 потери производительности из-за приведения к ссылочному типу и восстановления из объектного образа можно нивелировать путем использования обобщений (generics), которые будут рассмотрены в главе 10.

Оглавление книги


Генерация: 1.295. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз