Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OSISP Part 3.DOC
Скачиваний:
43
Добавлен:
11.05.2015
Размер:
360.45 Кб
Скачать
  1. Общая система типов данных в среде .Net. Размерные и ссылочные типы данных.

В CLR каждый объект прямо или косвенно является производным от System.Object.

Открытые методы:

Equals Возвращает true, если два объекта имеют одинаковые значения.

GetHashCode Возвращает хеш-код для значения данного объекта. Этот метод следует переопределить, если объекты типа используются в качест­ве ключа в хеш-таблице. Очень неудачно, что этот метод опреде­лен в Object, потому что большинство типов не служат ключами в хеш-таблице; этот метод уместнее было бы определить в интер­фейсе.

ToString По умолчанию возвращает полное имя типа (this.GetTypeQutlName). На практике этот метод переопределяют, чтобы он возвра­щал объект String, содержащий состояние объекта в виде строки. Например, переопределенные методы для таких фундаментальных типов, как Boolean и Int32, возвращают значения объектов в стро­ковом виде. Кроме того, переопределение метода часто применяют при отладке; вызов такого метода позволяет получить строку, со­держащую значения полей объекта. Считается, что ToString «знает о Culturelnfo, связанном с вызывающим потоком.

GetType Возвращает экземпляр объекта, производного от type, который идентифицирует тип объекта, вызвавшего GetType. Возвращаемый объект Туре может использоваться с классами, реализующими от­ражение для получения информации о типе в виде метаданных Метод GetType невиртуальный, его нельзя переопределить, поэтому классу не удастся исказить сведения о своем типе. Таков механизм обеспечения безопасности типов.

Защищенные методы:

MemberwiseClone Этот невиртуальный метод создает новый экземпляр типа и при­сваивает полям нового объекта соответствующие значения объек­та this. Возвращается ссылка на созданный экземпляр

Finalize Этот виртуальный метод вызывается, когда сборщик мусора определяет, что объект является мусором, но до возвращения занятой объектом памяти в кучу. В типах, требующих очистки при сборке мусора, следует переопределить этот метод.

CLR поддерживает две разновидности типов: ссылочные (reference types) и значи­мые (value types). Большинство типов в FCL — ссылочные, но программисты чаще всего используют значимые. Память для ссылочных типов всегда выделяется из управляемой кучи, а оператор С# new возвращает адрес в памяти, где размещает­ся сам объект. При работе с ссылочными типами имейте в виду следующие об­стоятельства, относящиеся к производительности приложения:

■ память для ссылочных типов всегда выделяется из управляемой кучи;

■ каждый объект, размещаемый в куче, имеет некоторые дополнительные чле­ны, подлежащие инициализации;

■ незанятые полезной информацией байты объекта обнуляются (это касается полей);

■ размещение объекта в управляемой куче со временем инициирует сборку му­сора.

Если бы все типы были ссылочными, эффективность приложения резко упала бы. Представьте, насколько замедлится выполнение приложения, если при каж­дом обращении к значению типа Int32 будет выделяться память! Поэтому, чтобы ускорить обработку простых, часто используемых типов, CLR предлагает «облег­ченные» типы — значимые. Экземпляры этих типов обычно размещаются в стеке потока (хотя они могут быть встроены и в объект ссылочного типа). В представ­ляющей экземпляр переменной нет указателя на экземпляр; поля экземпляра раз­мещаются в самой переменной. Поскольку переменная содержит поля экземпля­ра, то для работы с экземпляром не нужно выполнять разыменовывание (derefe­rence) экземпляра. Благодаря тому, что экземпляры значимых типов не обраба­тываются сборщиком мусора, уменьшается интенсивность работы с управляемой кучей и сокращается количество наборов (collections), требуемых приложению на протяжении его существования.

В документации по .NET Framework можно сразу увидеть, какие типы относят к ссылочным, а какие — к значимым. Если тип называют классом (class), речь идет о ссылочном типе. Так, классы SystemObject, SystemException, SystemJOfileStream

и SystemRandom — это ссылочные типы. В свою очередь значимые типы в доку­ментации называют структурами (structure) и перечислениями (enumeration). Например, структуры SystemInt32, System Boolean, SystemDecimal, System.TimeSpan и перечисления System DayOFWeek, System IOFileAttributes и SystemDrawingFontStyle являются значимыми типами.

При внимательном знакомстве с документацией можно заметить, что все струк­туры являются прямыми потомками абстрактною типа SystemValueType, который в свою очередь является производным от тина System.Object. По умолчанию все значимые типы должны быть производными от SystemValueType. Все перечисле­ния являются производными от типа SystemEnum, производного от SystemValueType. CLR и языки программирования по-разному интерпретируют перечисления.

При определении собственного значимого типа нельзя выбрать произвольный базовый тип, однако значимый тип может реализовать один или несколько выб­ранных вами интерфейсов. Кроме того, в CLR значимый тип является изолирован­ным, то есть не может служить базовым типом для какого-либо другого ссылочно­го или значимого типа. Поэтому, например, нельзя в описании нового типа указать в качестве базовых Boolean, Char, Int32, Uint64, Single, Double, Decimal и т. д.

■ Объекты значимого типа существуют в двух формах: неупакованной (unboxed) и упакованной (boxed). Ссылочные типы бывают только в упакованной форме.

■ Значимые типы являются производными от System.ValueType. Этот тип имеет те же методы, что и System.Object. Однако SystemValueType переопределяет ме­тод Equals, который возвращает true, если значения полей в обоих объектах совпадают. Кроме того, в SystemValueType переопределен метод GetHashCode, который создает значение хеш-кода с помощью алгоритма, учитывающего значения полей экземпляра объекта. Из-за проблем с производительностью в реализации по умолчанию, определяя собственные значимые типы значений, надо переопределить и написать свою реализацию методов Equals и GetHash­Code.

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

■ Переменные ссылочного типа содержат адреса объектов в куче. Когда пере­менная ссылочного типа создается, ей по умолчанию присваивается null, то есть в этот момент она не указывает на действительный объект. Попытка задейство­вать переменную с таким значением приведет к генерации исключения Null-ReferenceException. В то же время в переменной значимого типа всегда содер­жится некое значение соответствующего типа, а при инициализации всем членам этого типа присваивается 0. Поскольку переменная значимого типа не является указателем, при обращении к значимому типу исключение NullRefe-renceException возникнуть не может. CLR поддерживает понятие особого вида значимого типа, допускающего присваивание null, (mailable types).

■ Когда переменной значимого типа присваивается другая переменная значи­мого типа, выполняется копирование всех ее полей. Когда переменной ссы­лочного типа присваивается переменная ссылочного типа, копируется только ее адрес.

■ Вследствие сказанного в предыдущем абзаце, несколько переменных ссылоч­ного типа могут ссылаться на один объект в куче, благодаря чему, работая с одной переменной, можно изменить объект, на который ссылается другая пе­ременная. С другой стороны, каждая переменная значимого типа имеет соб­ственную копию данных «объекта», и операции с одной переменной значимого типа не повлияют на другую переменную.

■ Так как неупакованные значимые типы не размещаются в куче, память, отве­денная для них, освобождается сразу при возвращении управления методом, в котором описан экземпляр этого типа. Это значит, что экземпляр значимого типа не получает уведомления (через метод Finalize), когда его память осво­бождается.

  1. Упаковка и распаковка размерных типов данных в среде .NET.

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

1. В управляемой куче выделяется память. Ее объем определяется длиной значи­мого типа и двумя дополнительными членами, необходимыми для всех объектов в управляемой куче, — указателем на объект-тип и индексом SyncBlocklndex.

2. Поля значимого типа копируются в память, выделенную только что в куче.

3. Возвращается адрес объекта. Этот адрес является ссылкой на объект; значимый тип превратился в ссылочный.

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

Распаковка в два этапа. Сначала извлекается адрес полей Point из упакованного объекта Point. Этот процесс называют распаковкой (unboxing). Затем значения полей копируются из кучи в экземпляр значимого тина, находящийся в стеке.

При распаковке ссылочного типа происходит следующее.

1. Если переменная, содержащая ссылку на упакованный значимый тип, равна null, генерируется исключение NullReferenceException.

2. Если ссылка указывает на объект, не являющийся упакованным значением тре­буемого значимого типа, генерируется исключение InvalidCastException

Когда выполняется распаковка объекта, должно быть сделано приведение к неупакованному типу.

C# имеет унифицированную систему типов, таким образом, значение любого типа может интерпретироваться как объект. Любой тип в C#, прямо или косвенно, является наследником класса object. Ссылочные типы рассматриваются как простые объекты типа object. Типы-значения - как результат выполнения операции приведения типов. Типы данных в C# разделяются на ссылочные типы и типы-значения. К типам-значениям относятся: – Простые • целочисленные (int - 32 бита, long - 64 бита) • char (16 бит, Unicode) • типы с плавающей точкой (могут выдавать обычные значения, +0, -0, +∞, -∞, NaN) • decimal (128-бит, с точностью до 28 знаков) – Структурные – Перечислимые: enum Days { Mon=1, Tue … }, по умолчанию типа int. К типам-значениям относится широкий набор примитивных типов данных, включая целые числа различной разрядности, типы с плавающей запятой различной точности, специальный тип decimal с фиксированной точностью, предназначенный для финансовых вычислений, а также символьный тип char, способный хранить символы в формате Unicode и потому удобный при разработке интернациональных приложений. Все целочисленные типы существуют в двух вариантах: знаковом и беззнаковом. Важной особенностью переменных с плавающей запятой является то, что операции над ними никогда не производят исключений, но зато результатом работы с ними могут быть значения ±∞ (как результат деления на ноль) или нечисловым значением, NaN (Not-ANumber, как результат деления 0 на 0 или операций, в котором один из операндов уже равняется NaN). Отметим, что C# содержит также специальный тип для булевских значений; переменные булевского типа могут содержать значения true или false, но в отличие от большинства современных языков программирования этим значениям не соответствует никаких численных эквивалентов Ссылочные типы • Тип object (для упаковки значений) • Тип class • Интерфейсы • Представители delegates) • Тип string • Массивы. Интерфейс представляет собой ссылочный тип, который может иметь только абстрактные элементы (аналогично методам, равным нулю, в С++). В частности, с помощью интерфейсов можно реализовать механизм множественного наследования — для этого необходимо унаследовать класс от нескольких элементов и затем явным образом реализовать заявленную функциональность. Представители (delegates) являются относительно безопасной версией указателей на функции: окружение .NET гарантирует, что представители указывают именно на допустимый объект, а не просто на некоторый адрес в памяти. Основные области применения представителей — это методы обратного вызова и асинхронные обработчики событий. Строки в C# являются полноценным ссылочным типом, но при этом обладают семантикой сравнений, характерной для типов-значений (т.е. строки равны, если равны их значения). Это можно проиллюстрировать следующим примером. Массивы в С# бывают двух типов: многомерные (например, int [,,] определяет трехмерный массив) и невыровненные (они же массивы массивов, используемые в С++; например, int [] [] определяет двухмерный массив). Несмотря на простой внешний вид, массивы являются полноценными объектами, представляющими класс System.Array. Упаковка-преобразование представляет собой процесс преобразования типа значения в тип object или любой другой тип интерфейса, реализуемый этим типом значения. Когда тип значения упаковывается средой CLR, она создает программу-оболочку значения внутри System.Object и сохраняет ее в управляемой куче. Операция распаковки-преобразования извлекает тип значения из объекта.

  1. Ссылочные типы данных. Объектная модель в среде .NET и языке C#.

Объектная модель представления данных оперирует такими понятиями, как класс и объект. Классы определяют структуру данных и представляют собой набор атрибутов (текстовая строка, целое число, изображение и т.д.). Представители класса (объекты) имеют определенную структуру и могут содержать другие объекты, образуя произвольную иерархическую структуру. Объекты могут наследовать свойства, содержание и поведение объектов, которые в них содержатся.

  1. Модели ручной и автоматической утилизации динамической памяти, их сравнительная характеристика.

Редкая программа может обойтись без использования динамических структур данных, таких как списки, деревья, массивы переменной длины, графы. Заранее предусмотреть и разместить эти данные в памяти невозможно, поэтому программы запрашивают память для данных динамически, по мере необходимости.

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

модель с ручным освобождением памяти;

модель со счетчиком ссылок;

модель с иерархией владения;

модель с автоматической «сборкой мусора»;

модель с автоматической «сборкой мусора» и принудительным освобождением памяти.

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

Это наиболее распространенная модель. В распоряжении программиста есть две процедуры или два оператора, с помощью которых он может соответственно запрашивать и освобождать участки (блоки) памяти. В языке программирования Cи для этой цели служат соответственно процедуры malloc и free, а в языке C++ — операторы new и delete. Эти операторы мощнее упомянутых процедур, они позволяют создавать и уничтожать объекты в динамической памяти.

В модели с ручным освобождением памяти система не следит за наличием или отсутствием ссылок на объекты. Программист должен сам заботиться об уничтожении ненужных объектов и о возвращении их памяти системе.

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

Обычно список свободных блоков является двусвязным и хранится внутри свободной памяти. Перед добавлением в него освобождаемого блока памяти система выполняет дефрагментацию, сливая смежные свободные блоки в один.

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

Недостаток модели — ненадежность и подверженность ошибкам. В больших прикладных системах, где данные передаются между несколькими модулями, очень трудно поддерживать соответствие операторов delete операторам new, поэтому выделенная память может вообще никогда не освобождаться. Происходит так называемая утечка памяти: объекты уже не используются, ссылок на них уже нет, но система считает память занятой. «Утечки памяти» могут критически влиять на работоспособность программ, работающих продолжительное время (это относится к СУБД, прикладным серверам, системам управления физическими объектами и пр.).

Еще более опасно так называемое зависание ссылок, суть которого заключается в том, что в программе остаются ссылки на уничтоженные объекты. Если программа обращается по такой ссылке и изменяет данные, то она не только выполняет пустую работу, но, по всей вероятности, меняет служебные данные менеджера памяти, используемые для организации списка свободных блоков памяти. Такие ошибки очень трудно найти и исправить, поскольку возникающие из-за них сбои происходят не сразу, а спустя некоторое время, когда уже непонятно, какая подпрограмма нарушила целостность данных.

Еще один недостаток модели состоит в том, что при интенсивном выделении и освобождении памяти, как правило, возникает сильная фрагментация — выделенные блоки памяти перемежаются занятыми блоками. В результате может наступить момент, когда суммарный объем свободной памяти очень велик, но сплошного участка нужного размера нет. При этом выполнить дефрагментацию невозможно, поскольку созданные объекты нельзя перемещать в адресном пространстве программы (ведь неизвестно, где в программе имеются ссылки на эти объекты, а значит, ссылки невозможно правильно корректировать).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]