Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Ссылочные и важные типы данных в CLR via C# (часть 2)

Anna | 18.06.2014 | нет комментариев
В C# все типы объявленные с ключевым словом struct являются важными, как class — ссылочными. Разницы в их поведении не отслеживается, следственно особенно значимо понимать какой тип применяется в программе, так как это может гораздо влиять на эффективность в программе.
Разглядим пример, из которого видна разница между ссылочными и важными типами:

 //Ссылочный тип, так как объявлено class
class Reference 
{
    public Int32 x {get; set;} // тут применяется сокращенный способ объявления свойств, подробнее читайте книгу "Библия С#" М. Фленова
}

//Значимый тип, так как объявлено struct
struct Structure
{
    public Int32 x {get; set;}
}

static void Main()
{
   Reference r1 = new Reference(); //размещается в куче
   Structure s1 = new Structure(); //размещается в стеке
   r1.x =  5; //разыменование указателя (обращения к значению в памяти, на которое указывает указатель, подробнее операции над указателями)

   s1.x = 10; //изменения в стеке
  Console.WriteLine(r1.x); // итог 5
  Console.WriteLine(s1.x);  //вывод 10

   Reference r2 = r1; //копируется только ссылка, указатель
   Structure s2 = s2; //помещается в стек и копируются поля
   r1.x = 8 // изменяется и r1.x и r2.x
   s1.x = 9 // изменяется только s1.x, но не s2.x
  Console.WriteLine(r1.x); // итог 8
  Console.WriteLine(r2.x);  //вывод8
  Console.WriteLine(s1.x); // итог 9
  Console.WriteLine(s2.x);  //вывод 10
 }

Как видно из примера, дозволено подметить, что при работе с ссылочными и важными типами отслеживается значительная разница. При создании ссылочных типов выдается память в куче и возвращается адрес в памяти, тот, что сохраняется в переменной. Следственно при инициализации переменной такого же типа и присвоения ей того же значения, то копируется только адрес на область в памяти. Как и происходит в строке «Reference r2 = r1; //копируется только ссылка, указатель». То есть 2 переменные указывают только на одну область памяти.

В тоже время вовсе другое происходит при работе со важными типами. При создании новой переменной важного типа и копировании значений, происходит новое выделение в стеке памяти и создание новой само­стоятельной переменной. «Structure s2 = s2; //помещается в стек и копируются поля»
Исходя из выше сказанного дозволено подметить также, что при изменении полей в ссылочном типе происходит метаморфоза значений, на которые ссылаются переменные. То есть в данном примере переменные r1.x и r2.x покажут идентичное значение, даже если изменить к примеру r1.x, так как обе переменные указывают на одну область памяти. А вот если изменить s1.x, то метаморфоза s2.x не последует, так как s1.x и s2.x это две различные переменные, которые никак не связаны между собой.

Немножко отступим от темы, но это имеет прямое отношение к ссылочному типу. Разглядим такой оператор как new. С его поддержкой и только создаются и инициализируются все ссылочные типы. Опишу я оператор new всецело и постараюсь объяснить всякое непонятное слово.

Оператор new действует так:

  • Вычисляется число байтов, нужных каждому экземплярным полям типа и каждому его базовым типам, включая System.Object (исходя из наследственности, производному классу, типу и т.д. наследуется все способы базового класса). Всякий объект кучи требует дополнительных членов, они именуются указатель на объект-тип(type object) и индекс блока синхронизации(sync block index) и служат CLR для управления объектом.
  • Выдается память для объекта, резервируя нужное для данного типа число байтов в управляемой куче байтов, после этого все байты устанавливаются в нуль.
  • Инициализируется указатель на объект-тип и индекс блока синхронизации.
  • Вызывается конструктор экземпляра типа с параметрами либо без. При этом если конструктор не объявлен в коде, компилятор механически вызовет конструктор. При этом множество компиляторов вызывает код конструктора базового класса, в частности конструктор System.Object, но он ничего не делает и легко возвращает управление.

Указатель на объект-тип, данный член разрешает определить тип данного объекта(экземпляра).
Данный указатель использует такой способ как .GetType(), он разрешает определить какой тип у данного объекта. Еще дозволено применять выражение typeof, но об этом потом. А индекс блока синхронизации применяется для хранения данных при многопоточном выполнении программы. А также применяется при вызове .GetHashCode(). Подробнее дозволено прочитать в документации .NET «Внутреннее устройство .NET Framework — как CLR создает объекты периода выполнения».

При этом у оператора new нет пары — оператора delete. Как я писал в предыдущей статье, CLR сам занимается сборкой мусора в управляемой куче, механически находит непотребные объекты и уничтожает их.
Исходя из выше сказанного: проектируя свой личный тип, проверьте, какой тип отменнее каждого применять. Это помогает усовершенствовать результативность кода. Вот несколько условий, когда дозволено применять важный тип:

  • Тип ведет себя аналогично примитивному типу. Это обозначает что он довольно примитивный и у него нет членов, способных изменять экземпляры классов. Изредка говорят, что данный тип неизменяемый (immutable). Рекомендуется многие важнейшие типы помечать спецификатором readonly. Это подобие const, но при этом переменную необходимо сразу инициализировать, а при readonly переменную дозволено объявить без заблаговременной инициализации. Комфортно применять к примеру в конструкторах, когда объявляем непрерывную переменную, а в конструкторе ее инициализируем.
  • Типу не необходим всякий иной тип, в качестве базового
  • Тип не будет иметь производных от него типов

Но при этом необходимо рассматривать тот факт, что поля переменных, которые являются доводом и передаются по назначению, то они копируются, что в свою очередь приводит к снижению продуктивности. Следственно, способ, возвращающий важный тип, приводит к копированию полей экземпляра, что снижает результативность работы программ. Следственно, необходимо еще кое-что рассматривать, а именно:

  • Размер экземпляров типа мал (приблизительно 16 байт либо поменьше)
  • Размер экземпляров огромнее 16 байт, но при этом нет передаваемых доводов либо способ не возвращает значение в конце своего выполнения.

Безусловно, у важных типов есть свои превосходства перед ссылочными типами, но при этом есть и недочеты. Вот некоторые особенности, отличающие ссылочные и важные типы.

  • Объекты важного типа существуют в 2-х формах: неупакованной (unboxed) и упакованной (boxed ). Ссылочные типы бывают только в упакованной форме.
  • От того что в объявлении нового важного либо ссылочного типа невозможно указывать важный тип в качестве базового класса, создавать в важном тип новые виртуальные способы невозможно. Способы не могут быть абстрактными и неявно являются изолированными (то есть их невозможно переопределить)
  • Переменные ссылочного типа содержат адреса объектов в куче. Когда перемененная ссылочного типа создается, ей по умолчанию присваивается null, то есть в данный момент она не указывает на действительный объект. Попытка задействовать переменную с таким значением приведет к генерации исключения NullReferenceException. В то же время в переменной важного типа неизменно содержится некое значение соответствующего типа, а при инициализации каждому членам этого типа присваивается. От того что переменная важного типа не является указателем, при обращении к важному типу исключение NullReferenceException появиться не может. CLR поддерживает представление важного типа специального вида, допускающего присваивание null (nullable types).
  • Когда переменной важного типа присваивается иная перемененная важного типа, выполняется копирование всех ее полей. Когда переменной ссылочного типа присваивается перемененная ссылочного типа, копируется ТОЛЬКО ее адрес.
  • В итоге сказанного в предыдущем абзаце, несколько переменных ссылочного типа могут ссылаться на один объект в куче, вследствие чему, работая с одной переменной, дозволено изменить объект, на тот, что ссылается иная переменная. В то же время всякая перемененная важного типа имеет собственную копию данных объекта, следственно операции с одной переменной важного типа не влияют на иную переменную.
  • Так как неупакованные важнейшие типы не размещаются в куче, отведенная для них память освобождается сразу при возвращении управления способом, в котором описан экземпляр этого типа.

Следственно применяя познания, необходимо особенно полно применять все источники системы, при этом не теряя продуктивность и экономно расходовать источники.

В дальнейшей статье разглядим упаковку и распаковку важных типов.

 Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB