понедельник, 8 сентября 2014 г.

boxing/unboxing - распаковка/упаковка в C#

Итак - у нас в языке C# есть размерные типы ( хранятся в стеке-value types) и ссылочные ( живут в куче - reference types). Размерные - простые и обычно маленькие ( ибо опять же стек не резиновый), ссылочные - большие ( и представляют собой ссылку на область памяти где начинается объект).
Проблема №1 (при копировании ссылочного типа создается еще один указатель на одну и ту же область памяти !)
// Ссылочный тип (поскольку 'class'),
class SomeRef { public Int32 x; }
// Размерный тип (поскольку 'struct'),
struct SomeVal { public Int32 x; }
static void ValueTypeDemoO {
SomeRef r1 = new SomeReff); // Размещается в куче.
SomeVal v1 = new SomeValf); // Размещается в стеке.
г1.х = 5; // Разыменовываем указатель,
vl.x = 5; // Изменения в стеке.
Console.WriteLine(rl.x); // Отображается "5".
Console.Writel_ine(v1 .x); // Также отображается "5".

SomeRef г2 = г1; // Копируется только ссылка (указатель).
SomeVal v2 = v1; // Помещаем в стек и копируем члены.
г1.х = 8; // Изменяются г1.х и г2.х. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
vl.x = 9; // Изменяется vl.x, но не v2.x.
Console.WriteLine(rl.x); // Отображается "8".
Console.WriteLine(r2.x); // Отображается "8". Хотя в коде видно изменение лишь r1.x
Console.WriteLine(vl.x); // Отображается "9".
Console.WriteLine(v2.x); // Отображается "5". В принципе интуитивно понятно



Проблема №2(boxing/unboxing) - при приведении размерного типа к ссылочному и обратно - гоняем данные из стека в память и обратно ( откуда тормоза ! )


// Объявляем размерный тип.
struct Point {
public Int32 x, у;
}
static void Main() {
Point p;
p.x = p.у = 1;
Object о = p; // Упаковка р; о указывает на упакованный объект.
р = (Point) о; // Распаковка о и копирование полей из объекта в стек.
}
В принципе однократно это не столь критично - а вот в цикле могут быть серьезные тормоза !

Комментариев нет :

Отправить комментарий