- •Сборки (assembly) в среде .Net. Проблема версионности сборок и ее решение.
- •Номер версии в .Net
- •Сведения о версии
- •Номер версии сборки
- •Информационная версия сборки
- •Общая система типов данных в среде .Net. Размерные и ссылочные типы данных. Типы, переменные и значения
- •Пользовательские типы
- •Система общих типов cts
- •Ссылочные типы
- •Типы литеральных значений
- •Неявные типы, анонимные типы и типы, допускающие значение null
- •Упаковка и распаковка размерных типов данных в среде .Net.
- •Производительность
- •Упаковка–преобразование
- •Распаковка-преобразование
- •Ссылочные типы данных. Объектная модель в среде .Net и языке c#.
- •Модели ручной и автоматической утилизации динамической памяти, их сравнительная характеристика. Модель с ручным освобождением памяти
- •Модель с автоматической «сборкой мусора»
- •Модель автоматической утилизации динамической памяти, основанная на сборке мусора. Проблема недетерминизма.
- •Модель автоматической утилизации динамической памяти, основанная на аппаратной поддержке (тегированной памяти).
- •Сборка мусора в среде .Net. Построение графа достижимых объектов.
- •Сборка мусора в среде .Net. Механизм поколений объектов.
- •Модель детерминированного освобождения ресурсов в среде .Net. Интерфейс iDisposable и его совместное использование с завершителем (методом Finalize).
- •«Мягкие ссылки» и кэширование данных в среде .Net.
- •Краткие и длинные слабые ссылки
- •Краткая ссылка
- •Длинная ссылка
- •Правила использования слабых ссылок
- •Динамические массивы в среде .Net и языке c#.
- •Приведение типов в массивах
- •Все массивы неявно реализуют /Enumerable, /Collection и iList
- •Передача и возврат массивов
- •Создание массивов с ненулевой нижней границей
- •Производительность доступа к массиву
- •Небезопасный доступ к массивам и массивы фиксированного размера
- •Делегаты в среде .Net и механизм их работы. Знакомство с делегатами
- •Использование делегатов для обратного вызова статических методов
- •Использование делегатов для обратного вызова экземплярных методов
- •Правда о делегатах
- •Использование делегатов для обратного вызова множественных методов (цепочки делегатов)
- •Поддержка цепочек делегатов в с#
- •Расширенное управление цепочкой делегатов
- •Упрощение синтаксиса работы с делегатами в с#
- •Упрощенный синтаксис № 1: не нужно создавать объект-делегат
- •Упрощенный синтаксис № 2: не нужно определять метод обратного вызова
- •Упрощенный синтаксис № 3: не нужно определять параметры метода обратного вызова
- •Упрощенный синтаксис № 4: не нужно вручную создавать обертку локальных переменных класса для передачи их в метод обратного вызова
- •Делегаты и отражение
- •События в среде .Net; реализация событий посредством делегатов. События
- •Этап 1: определение типа, который будет хранить всю дополнительную информацию, передаваемую получателям уведомления о событии
- •Этап 2: определение члена-события
- •Этап 3: определение метода, ответственного за уведомление зарегистрированных объектов о событии
- •Этап 4: определение метода, транслирующего входную информацию в желаемое событие
- •Как реализуются события
- •Создание типа, отслеживающего событие
- •События и безопасность потоков
- •Явное управление регистрацией событий
- •Конструирование типа с множеством событий
- •Исключительные ситуации и реакция на них в среде .Net. Достоинства
- •Механика обработки исключений
- •Блок try
- •Блок catch
- •Блок finally
- •Генерация исключений
- •Определение собственных классов исключений
- •Исключения в платформе .Net Framework
- •Исключения и традиционные методы обработки ошибок
- •Управление исключениями средой выполнения
- •Фильтрация исключений среды выполнения
- •21 Средства многопоточного программирования в среде .Net. Автономные потоки. Пул потоков.
- •Создание и использование потоков
- •Запуск и остановка потоков
- •Методы управления потоками
- •Безопасные точки
- •Свойства потока
- •Потоки Windows в clr
- •К вопросу об эффективном использовании потоков
- •Пул потоков в clr
- •Ограничение числа потоков в пуле
- •22. Асинхронные операции в среде .Net. Асинхронный вызов делегатов.
- •23. Синхронизация программных потоков в среде .Net. Блокировки.
- •Двойная блокировка
- •Класс ReaderWriterLock
- •Использование объектов ядра Windows в управляемом коде
- •Вызов метода при освобождении одного объекта ядра
- •24. Синхронизация программных потоков в среде .Net. Атомарные (Interlocked-операции). Семейство lnterlocked-методов
- •25. Прерывание программных потоков в среде .Net. Особенности исключительной ситуации класса ThreadAbortException.
- •26. Мониторы в среде .Net. Ожидание выполнения условий с помощью методов Wait и Pulse. Класс Monitor и блоки синхронизации
- •«Отличная» идея
- •Реализация «отличной» идеи
- •Использование класса Monitor для управления блоком синхронизации
- •Способ синхронизации, предлагаемый Microsoft
- •Упрощение кода c# при помощи оператора lock
- •Способ синхронизации статических членов, предлагаемый Microsoft
- •Почему же «отличная» идея оказалась такой неудачной
- •Целостность памяти, временный доступ к памяти и volatile-поля
- •Временная запись и чтение
- •Поддержка volatile-полей в с#
- •27. Асинхронный вызов делегатов.
- •Общие типы (Generics)
- •Инфраструктура обобщений
- •Открытые и закрытые типы
- •Обобщенные типы и наследование
- •Проблемы с идентификацией и тождеством обобщенных типов
- •«Распухание» кода
- •Обобщенные интерфейсы
- •Обобщенные делегаты
- •Обобщенные методы
- •Логический вывод обобщенных методов и типов
- •Обобщения и другие члены
- •Верификация и ограничения
- •Основные ограничения
- •Дополнительные ограничения
- •Ограничения конструктора
- •Другие вопросы верификации
- •Приведение переменной обобщенного типа
- •Присвоение переменной обобщенного типа значения по умолчанию
- •Сравнение переменной обобщенного типа с null
- •Сравнение двух переменных обобщенного типа
- •Использование переменных обобщенного типа в качестве операндов
- •Преимущества использования общих типов
- •29. Итераторы в среде .Net. Создание и использование итераторов.
- •Общие сведения о итераторах
Динамические массивы в среде .Net и языке c#.
В языке C# массивы являются объектами, а не просто смежными адресуемыми областями памяти, как в C и C++. Array является абстрактным базовым типом для всех типов массивов. Можно использовать свойства и другие члены класса, которые имеет Array.
Класс Array является базовым для реализаций языка, поддерживающих работу с массивами. Тем не менее, явно наследовать класс Array может только система и компиляторы. Пользователи должны применять конструкции массивов, предоставляемые языком программирования.
Элементом называется значение, содержащееся в объекте Array. Длина объекта Array равна общему числу элементов, которые могут в нем содержаться. Ранг объекта Array равен размерности объекта Array. Нижняя граница измерения объекта Array является начальным индексом этого измерения объекта Array; в многомерном массиве Array у каждого измерения могут быть свои нижние границы.
|
В .NET Framework версии 2.0 класс Array реализует универсальные интерфейсы System.Collections.Generic.IList<T>,System.Collections.Generic.ICollection<T>иSystem.Collections.Generic.IEnumerable<T>. Реализации предоставляются массивам во время выполнения и, следовательно, остаются невидимыми для средств построения документации. Как следствие, универсальные интерфейсы не отображаются в синтаксисе объявления класса Array, и в справке отсутствуют разделы, касающиеся членов интерфейса, доступ к которым можно получить путем приведения массива к универсальному типу интерфейса (явным реализациям интерфейса). Главное, о чем нужно помнить, приводя массив к одному из этих интерфейсов, — это то, что члены, добавляющие, вставляющие или удаляющие элементы выбрасывают исключениеNotSupportedException. |
Объекты Typeпредоставляют сведения об объявлениях типов массивов. Объекты Array с одинаковым типом массива используют один и тот же объектType.
Свойство Type.IsArrayи методType.GetElementTypeмогут не возвращать ожидаемые результаты в объекте Array, поскольку в случае приведения массива к типу Array, результатом является объект, а не массив. Это означает, что typeof(System.Array).IsArray возвращает значение false, а typeof(System.Array).GetElementType возвращает значение null.
В отличие от большинства классов в классе Array предусмотрен метод CreateInstance, используемый вместо открытых конструкторов для получения доступа с поздней привязкой.
Метод Array.Copyкопирует элементы из массива в массив, не только когда типы этих массивов совпадают, но и когда они различны; приведение типов при этом выполняется автоматически.
Некоторые методы, такие как CreateInstance,Copy,CopyTo,GetValueиSetValue, предоставляют возможность перегрузок, которые принимают 64-разрядные целые числа в качестве параметров для работы с массивами большой емкости. СвойствоLongLengthи методGetLongLengthвозвращают 64-разрядные целые числа, указывающие длину массива.
Сортировка объекта Array не гарантируется. Объект Array должен быть отсортирован до выполнения операций (таких, как BinarySearch), для которых требуется сортировка объекта Array.
//----------------------------Рихтер
Массивы — это механизм объединения отдельных элементов в набор, рассматриваемый как единое целое. Общеязыковая исполняющая среда Microsoft .NET (CLR) поддерживает массивы одномерные (single-dimension), многомерные (multidimen-sion) и вложенные (jagged). Базовым для всех массивов является тип SystemArray, производный от System.Object. А это значит, что массивы всегда относятся к ссылочному типу и размещаются в управляемой куче, а переменная в приложении содержит не сам массив, а ссылку на него. Поясню это на примере:
Int32[] mylntegers; // Объявляем ссылку на массив.
mylntegers = new Int32[100]; // Создаем массив из 100 элементов типа Int32.
В первой строке объявляется переменная mylntegers для хранения ссылки на одномерный массив элементов типа Int32. Вначале mylntegers присваивается null, так как память под массив пока не выделена. Во второй строке выделяется память под 100 значений типа Int32; все они инициализируются 0. Поскольку массивы относятся к ссылочным типам, блок памяти для хранения 100 неупакованных экземпляров Int32 выделяется в управляемой куче.
Вообще говоря, помимо элементов массива в блоке памяти также размещается указатель на объект-тип и SyncBlocklndex, а также некоторые дополнительные члены. Возвращенный адрес этого блока памяти заносится в переменную mylntegers.
Аналогично создается и массив элементов ссылочного типа:
Control[] myControls; // Объявляем ссылку на массив.
myControls = new Control[50]; // Создаем массив из 50 ссылок на Control.
В первой строке объявлена переменная myControls для размещения ссылки на одномерный массив ссылок на элементы Control. Вначале myControls присваивается null, ведь память под массив не выделена. Во второй строке выделяется память под 50 ссылок на Control; все эти ссылки инициализируются значением null. Поскольку Control относится к ссылочным типам, то создание массива сводится только к созданию ссылок; реальные объекты в этот момент не создаются. Возвращенный адрес блока памяти заносится в переменную myControls.
Вот как выглядят массивы значимого и ссылочного типов в управляемой куче (рис. 13-1).
Рис. 13-1. Массивы значимого и ссылочного типов в управляемой куче
На этом рисунке показан массив Controls после выполнения таких операторов:
myControls[1] = new ButtonQ;
myControls[2] = new TextBoxO;
myControls[3] =myControls[2]; // Два элемента ссылаются на один и тот же объект.myControls[46] =newDataGridO;
myControls[48] = new ComboBoxQ;
myControls[49] = new ButtonQ;
Согласно общеязыковой спецификации (CLS), нумерация элементов в массиве должна начинаться с нуля. Тогда методы, написанные на С#, смогут передать ссылку на созданный массив коду, написанному на другом языке, скажем, на Microsoft Visual Basic .NET. Кроме того, поскольку массивы с начальным нулевым индексом получили очень большое распространение, Microsoft постаралась оптимизировать их работу. Тем не менее в CLR допускаются и иные варианты индексации массивов, хотя это не приветствуется. Те, для кого вопросы производительности и межъязыковой совместимости программ не имеют большого значения, могут узнать о создании и использовании массивов, начальный индекс которых отличен от 0, далее в этой главе.
Из рис. 13-1 видно, что в каждом массиве есть некоторая дополнительная информация (overhead). Это сведения о размерности массива (числе измерений), его нижней границе (чаще всего 0) и числе элементов в каждом измерении. Здесь же указан тип элементов массива. Ниже мы рассмотрим методы, позволяющие запрашивать эти данные.
Пока что нам встречались только одномерные массивы. Желательно ограничиться одномерными массивами с нулевым начальным индексом, которые называют иногда векторами. Векторы обеспечивают лучшую производительность, поскольку для операций с ними используются специальные IL-команды, такие как newarr, Idelem, Idelema, Idlen и stelem. Но если вам больше подходят многомерные массивы — пожалуйста. Вот некоторые примеры использования многомерных массивов:
// Создаем двумерный массив Doubles.
Doublet[,] myDoubles = new Double[10,9];
CLRподдерживает также вложенные (jagged) массивы. Производительность у одномерных вложенных массивов с нулевым начальным индексом такая же, как у обычных векторов. Однако обращение к элементу вложенного массива означает обращение к двум или больше массивам одновременно.
Вот пример массива многоугольников, где каждый многоугольник состоит из массива экземпляров Point:
//Создаем одномерный массив массивов Point.
Point[][] myPolygons = new Point[3][];
// myPolygons[0] ссылается на массив из 10 экземпляров Point.
myPolygons[0] =newPoint[10];
// myPolygons[1] ссылается на массив из 20 экземпляровPoint.
myPolygons[1] = new Point[20];
// myPolygons[2] ссылается на массив из 30 экземпляров Point.
myPolygons[2] = new Point[30];
// Отображаем точки первого многоугольника,
for (Int32 х = 0; х < myPolygons[0].Length; x++)
Console.WriteLine(myPolygons[0][x]);
Примечание CLR проверяет корректность индекса массива. Иначе говоря, при обращении к элементу массива, состоящему, скажем, из 100 элементов (пронумерованных от 0 до 99), с индексом 100 или -5 генерируется исключение SystemlndexOutOfRangeException. Доступ к памяти за пределами массива нарушит безопасность типов и откроет потенциальную брешь в защите, недопустимую для верифицируемого кода в CLR. Обычно проверка выхода индекса за границы не имеет существенного значения для производительности, так как JIT-компилятор проверяет границы массивов обычно один раз перед выполнением цикла, а не при каждой итерации.