Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 11
Текст из файла (страница 11)
В этом отношении языки СЗ и ,Заза идентичны. Программисты С++ могут воспринимать переменные ссылочных типов как указатели, которые не нужно разыменовывать для доступа к объектам. Некоторые программисты С++ предпочитают думать об них как об "интеллектуальных" указателях. Часто под ссылочнылш типами в СЗ подразумеваются объекты, находящиеся в управляемой куче.
Однако для взаимодействия с объектами из управляемой кучи используется переменная ссылочноео пшпа. Переменные ссылочных типов имеют тип, ассоциированный с ними, и содержат указатель на объект, на который ссылаются. Например, тип ссылочной переменной может совпадать с классом, на который она указывает, с базовым типом объекта либо типом интерфейса, который данный объект реализует. Естественно, несколько переменных ссылочных типов могут указывать на один и тот же объект в одно и то же время.
В отличие от них, типы значений содержат в себе данные, а не указатели на данные. На рис. 3. 1 приведена диаграмма, описывающая сценарий. в котором две переменные ссылочного типа ссылаются на один и тот же объект в управляемой куче. На диаграмме показано, что каждая переменная ссылочного типа имеет ассоциированный с ней тип. 42 Глава 3 Рис. 3.1. Переменные ссылочных типов Типы значений Типы значений могут находиться как в стеке, так и в управляемой куче. Они обычно используются тогда, когда необходимо представить некоторые неизменяемые данные, обычно не занимающие много места в памяти.
Типы значений в СВ можно определять с использованием ключевого слова всгисс. На заметку! В следующем подзазделе будут описаны перечисления, которые объявляются с помощью ключевого слова епщп. Ключевое слово епщп также позволяет объявлять тип значений. Определенные пользователем типы значений ведут себя так же, как встроенные типы значений. При создании значения в потоке выполнения, это значение обычно создается в стеке, если только не является членом ссылочного типа.
Рассмотрим следующий фрагмент кода: 1пк Спейпвиег = 12; Яувгеи.Сопво1е.нгаке11пе( Спейпвнег.товкг1по() ) Экземпляр спейпвнегне только создается в стеке,попри передаче его методу этот методполучает его копию. Типы значений обычноиспользуются в управляемыхприложениях для представления облегченных порций или коллекций данных, подобно применению встроенных типов и структур в С++, а также примитивных типов дача. Эначения также могут находиться и в управляемой куче, но не сами по себе. Единственная возможность — это когда ссылочный тип имеет поле типа значения.
Несмотря на то что тип значения внутри объекта расположен в управляемой куче, он все равно ведет себя как тип значения в стеке, когда речь идет о передаче его методу; т.е. метод по умолчанию получит его копию. Любые изменения. внесенные в экземпляр значения, являются лишь локальными, если только значение не было передано по ссылке. Упомянутые концепции иллюстрируются в следующем коде. рсЬ11с вкгпсг Соогбапвке // тип значения ( риЫгс Тпв х; роЫ1с 1пг у; ) рсЫгс с1авв Епкгуро1пк // ссылочный тип ( рчЫгс вкаггс чогб йппеирстоноб1гусоогб( Соогб1паке соогб ) ( соогб.х = 1) соогб.у = 3; ) риЫгс вгаг1с чоаб Моб1гусоогб( геГ Соогб1пвке соогб ) ( соогб.х = 10) соогб.у = 10; Обзор синтаксиса С() 43 вгагтс тост) Мв1п() ( Соогстпвге 1осаггоп; 1освггоп.х = 50т 1освгсоп.у = 50т АССетрСТоМосггуСоогп( 1освСТоп )т Бувгвв.Сопво1е.нгсгеьспе( "( (О), (1) )", 1осаС1оп.х, 1освггоп.у )т МоостуСоого( гег 1освгсоп ); Бувееа.Сопво1е.нгггеъьпе( "( (О), (1) )", 1освг1оп.х, 1осагсоп.у ); ) ) В методе Мвтп вызов Агсевргтоиос(сгуСоогс( на самом деле ничего не делает со значением 1осагсоп.
Это объясняется тем, что Аггеяргтоиос(сбуСоого модифицирует локальную копию значения, которая была создана при вызове метода. В противоположность этому, значение 1осагтоп передается методу Мог(15уСоогс(по ссылке. Поэтому все изменения в методе Мок(сбуСоогс( в действительности проводятся над значением 1осагсоп из вызывающего контекста. Это подобно передаче значения через указатель в С++. Вывод этого примера выглядит так; ( 50, 50 ) ( 10, 10 ) Перечисления Перечисления (епюп) в СЗ подобны перечислениям в С++, и синтаксис их определения практически идентичен.
Однако в точке использования необходимо полносп ю квалифицировать значения иэ перечисления, используя имя типа этого перечисления. Все перечисления основаны на лежащем в основе целочисленном типе Тпс, если не указано иначе. Таким образом, перечисления также являются типами значений. На заметку! Лежащий з основе епци тил должен быть целочисленным, т.е. одним из следующих: Ьуге, вЬуге, влогг, цвпогг, Тпг, птпг, 1опо или п1опо. Каждая константа, определенная в перечислении, должна быть определена со значением, находящимся в пределах диапазона летавшего в основе типа.
Если значение константы перечисления не указано явно, принимается значение по умолчанию, равное 0 (еслн зто первая константа в перечислении) или значению предыдутцей константы, увеличенному на 1. Ниже показан пример перечисления на базе 1опо: рпЬ11с епов Со1ог: 1опо ( нес(, Бгееп = 50, В1ое ) Если в данном примере опустить двоеточие и ключевое слово 1опо после идентификатора типа Со1ог, то перечисление будет относиться к типу Тпг.
Обратите внимание, что значение Век( равно О. значение Огееп — 50. а значение В1ое — 51. Чтобы использовать это перечисление, напишите код вроде следующего: вгвг1с тоьс Мвгп() ( Со1ог со1ог = Со1ог.аео," Бувееа.Сопво1е.иг1геьспе( "Со1ог Тв (О)", со1ог.Тозггспд() )т ) 44 Глава 3 Если скомпилировать и запустить этот код на выполнение, можно увидеть, что в выводе на самом деле указывается имя перечисления, а не обычное значение О. За всю эту "магию" отвечает реализация метода Тозгг1пс () типа Буягев. Епцгп. Перечисления-флаги Константы перечисления часто используются для представления битовых флагов.
Чтобы сделать это явно, можно присоединить к перечислению атрибут из пространства имен Буясеп поимени Буясеп.е1здяАссг1ьъсе. Атрибут сохраняется в метаданных,и на него можно сослаться во время проектирования для определения того, предназначены ли члены перечисления для использования в качестве битовых флагов. Обратите внимание. что Бузят. Е1адяАСГгтЬиге не изменяет поведение значений, определенных перечислением. Однако во время выполнения некоторые компоненты могут использовать метаданные, сгенерированные атрибутом, для обработки значения иным образом.
Это отличный пример эффективного применения метаданных в стиле аспектно-ориентированного программирования (аярес1-ог(епгег( рго((гзгпгпгпй — АОР). На заметку! Понятие АОР также известное под названием аспектно-ориентированной разработки программного обеспечения (аярес1-опеп1еб во(Влаге Оеуе)оргпеп1 — АОЯ(О) — зто концепция, изначально разработанная Грегором Кицзалесом (Бгероцг К(ста)ея) и его командой из Хегох РАВС. При проектировании взаимодействующих единиц объектно-ориентированные методологии обычно замечательно справляются с разделением функциональности, или ответственности. Однако некоторые виды ответственности, называемые перекрестной ответственностью, не удается легко смоделировать в рамках стандартного объектно-ориентированного проектирования.
Например, предположим, что нужно протоколировать вход и выход в разные методы. Было бы сплошным кошмаром модифицировать код каждого метода, для которого требуется протоколирование. Намного проще было бы присоединить свойство — или в данном случае, атрибут — к самому методу, чтобы исполняющая система сама протоколировала его вызовы.
Это избавит от необходимости модифицировать метод, и такое требование применяется вне зависимости от его реализации. Сервер транзакций М)сгояой (М!сгозой Тгапяасбоп Зепгег— МТБ) стал одним из первых широко известных примеров внедрения АОР Используя метаданные и возможность присоединения произвольных специальных атрибутов к типам, методам, свойствам и т.д., вы с успехом можете применить концепции АОР в собственном проекте. Ниже приведен пример перечисления битовых флагов; (Е1ася) риб11с есор Ассеяяг1зоя ( НоАссеяя = Охо, Неаслссеяя = Ох1, Игтселссеяя = Ох2, Ехессгелссеяя = Охя А вот пример использования перечисления Ассеяяр1ася: яга11с то1с) Натп() ( Ассеяяр1зся ассеяя = Ассеяяг1адя.неаг)Ассеяя Ассеяяр1здя.иггсеАссеяя; Буягеа.сапяо1еЛг11еъгпе( "Ассеяя Тя (О)", ассеяя ) Если скомпилировать и запустить приведенный выше пример, вы увидите, что метод Еппа.
Тозгг1пп, неявно вызываемый из Жгтге) Епе, фактически выводит разделенный запятыми список всех битов, установленных в этом значении. Обзор синтаксиса С№ 45 Ссылочные типы Сборщик мусора (ОС) внутри СЬК управляет всем, что касается размещения объектов. Он может перемещать объекты в любое время.
При этом СЬЛ обновляет переменные, ссылающиеся на эти объекты. Обычно вас не заботит точное местоположение объекта в куче, и вам не нужно беспокоиться о том, перемещен он или нет. Но есть редкие случаи, например, при взаимодействии с "родными" РЫ.-библиотеками, когда может понадобиться получить прямой указатель памяти на объект в куче. Это возможно с помощью техники небезопасного (или неуправляелюэо] кода, однако эта тема выходит за рамки настоящей книги. На заметку! По соглашению термином объект обозначается экземпляр ссылочного типа, в то время как термином значение — экземпляр типа значений, но все экземпляры любого типа (ссылочного типа или типа значений) также унаследованы от типа оьтесс.











