close

Вход

Забыли?

вход по аккаунту

?

22 88 ООПиП Понкратов

код для вставкиСкачать
22. Общая система типов. Общеязыковая спецификация. Тип System.Object. Приведение типов. Операторы is и as. Пространства имен и сборки. Элементарные типы. Проверяемые и непроверяемые операции для элементарных типов.
CLR тесно связана с типами. Типы предоставляют определенную функциональность вашим приложениям и компонентам. Они являются механизмом, позволяющим коду, написанному на одном языке программирования, взаимодействовать с кодом, написанным на другом. Поскольку типы являются основой CLR, Microsoft создала формальную спецификацию - общую систему типов (Common Type System, CTS), описывающую определение типов и их поведение.
В спецификации CTS утверждается, что любой тип может содержать 0 или более членов. • Поле. Переменная, являющаяся частью состояния объекта. Поле идентифицируется своим именем и типом.
• Метод. Функция, выполняющая некоторое действие над объектом, зачастую изменяя его состояние. • Свойство. Для вызывающей стороны этот член выглядит как поле, но в реализации типа он выглядит как метод. Свойства позволяют типу, в котором они реализованы, проверка входные параметры и состояние объекта, прежде чем предоставить доступ к своим значениям и/или вычислять значения только при необходимости. Свойства также упрощают синтаксис обращения к типу. •Событие. Обеспечивают механизм взаимных уведомлений объектов. Так, кнопка может предоставлять событие, уведомляющее другие объекты о том, что ее щелкнули.
CTS также определяет правила для видимости типов и доступа к их членам. Например, если тип помечен как открытый (public), он экспортируется, видим и доступен любой сборке. С другой стороны, если тип помечен как сборочный (assembly) (в С# - internal), он видим и доступен только коду той сборки, в которой реализован. Вот допустимые варианты управления доступом к методам или полям.
• Закрытый Метод может быть вызван другими методами только из того же класса.
• Родовой Метод может быть вызван производными типами независимо от того, в какой они сборке. (protected).
• Родовой и сборочный Метод может быть вызван производными типами, но только если они определены в той же сборке. Многие языки (вроде С# и Visual Basic) не реализуют такое ограничение доступа. • Сборочный Метод может быть вызван любым кодом из той же сборки. (internal).
• Родовой или сборочный Метод может быть вызван производными типами из любой сборки и любыми типами из той же сборки. (protected internal).
• Открытый Метод доступен любому коду из любой сборки.
Кроме того, CTS определяет правила для наследования типов, виртуальных функций, времени жизни объектов и т. д. Общеязыковая спецификация
СОМ позволяет объектам, созданным на разных языках, взаимодействовать. CLR обеспечивает интеграцию языков и позволяет объектам, созданным на одном языке, быть "равноправными гражданами" кода, написанного на другом. Чтобы создать тип доступный из других языков, придется задействовать лишь те возможности языка, которые гарантированно доступны в других. Чтобы помочь в этом, Microsoft определила общеязыковую спецификацию (Common Language Specification, CLS), описывающую минимальный набор возможностей, который должен быть реализован производителями компиляторов, чтобы их продукты работали в CLR.
В частности, CLS определяет правила, которым должны соответствовать видимые извне типы, чтобы к ним можно было получить доступ из любых других CLS-Совместимых языков программирования. Минимальный набор функций, которые должны поддерживать все языки, определяется CLS.
Сформулируем саму суть правил CLS. В CLR каждый член - либо поле (данные), либо метод (действие). Это значит, что каждый язык должен быть способен предоставлять доступ к полям и вызывать методы.
Все типы - производные от System.Object
В CLR каждый объект прямо или косвенно является производным от System.Object. Это значит, что следующие определения типов идентичны:
//Тип, неявно порождаемый из Object
//Тип, явно порождаемый из Object
class Employee {}
class Employee : System. Object {}
Благодаря тому, что все типы, в конечном счете, являются производными от System.Object, любой объект любого типа гарантированно имеет минимальный набор методов. 1.Equals - Возвращает true, если два объекта имеют одинаковые значения.
2. GetHashCode - Возвращает хэш-код для значения, данного объекта.
3. ToString - На практике этот метод переопределяют, чтобы он возвращал объект String, в виде строки.
4. GetType - Возвращает экземпляр объекта, производного от Туре, который идентифицирует тип объекта.
CLR требует, чтобы все объекты создавались с помощью оператора new Employee е = new Employee("ConstructorParaml");
Оператор new делает следующее.
1. Выделяет память для объекта, резервируя в управляемой куче байты, необходимые для данного типа.
2. Инициализирует специальные члены объекта. 3. Вызывает конструктор экземпляра типа с параметрами, указанными при вызове new Выполнив все эти операции, new возвращает ссылку на вновь созданный объект. Кстати, у оператора new нет пары - оператора delete. Сборкой мусора занимается CLR.
Приведение типов
Одна из важнейших особенностей CLR - безопасность типов (type safety). В период выполнения тип объекта всегда известен CLR. Точно определить тип объекта позволяет GetType. При разработке программ часто прибегают к приведению объекта к другим типам. CLR разрешает привести тип объекта к его собственному типу или любому из его базовых типов. Например, в С# нет специального синтаксиса для приведения типа объекта к его базовому типу, поскольку такое приведение считается безопасным неявным преобразованием. Однако для приведения типа к производному от него типу разработчик на С# должен ввести операцию явного приведения. // Этот тип неявно порожден от System. Object. class Employee {}
class App {
public static void Main( ) {
// Приведение типа не требуется, так как new возвращает объект // Employee, a Object - это базовый тип для Employee Object о = new Employee( );
// Приведение типа обязательно, так как Employee - производный от // Object.
e = (Employee) о;
} }
Приведение типов в С# с помощью операторов is и as
В С# есть другие механизмы приведения типов. Так, например, оператор is проверяет совместимость объекта с данным типом, а в качестве результата выдает значение типа Boolean: true или false. Оператор is никогда не генерирует исключение. Взгляните на код:
System.Object о = new System.Object( ):
System.Boolean bl = (o is System.Object); // bl - true.
System.Boolean b2 = (o is Employee); // b2 - false.
Если ссылка на объект равна null, оператор is всегда возвращает false, так как нет объекта, для которого нужно определить тип. Обычно оператор is используется так;
if (о is Employee) { Employee e = (Employee) о;
// Используем е внутри оператора if }
В этом коде CLR проверяет тип объекта фактически дважды: сначала в операторе is определяется совместимость о с типом Employee, а затем в теле оператора if происходит анализ, является ли о ссылкой на Employee. Поскольку такая схема встречается в программировании часто, в С# предложен механизм, повышающий эффективность кода с помощью оператора as:
Employee e = о as Employee; if (e != null) {// Используем е внутри оператора "if}
В этом коде CLR проверяет совместимость о с типом Employee, если это так, as возвращает ненулевой указатель на тот же объект. Если о и тип Employee несовместимы, оператор as возвращает null. Заметьте: оператор as заставляет CLR определить тип
объекта только раз, а if лишь сравнивает е с null - такая проверка намного эффективнее, чем определение типа объекта.
Оператор as отличается от приведения типа, по сути, только тем, что никогда не генерирует исключение. Если приведение типа невозможно, результатом является null.
Типы данных, которые поддерживаются компилятором напрямую, называются элементарными типами (primitive types). Так, С# - типу int соответствует System.Int32. Значит, весь следующий код компилируется без ошибок и преобразуется в одинаковые команды IL:
int a= 0;//Самый удобный синтаксис
System.Int32 a = 0; //Удобный синтаксис
Int a = new int( );//Неудобный синтаксис
System.Int32 a = new System.Int32( );//Неудобный синтаксис
С# разрешает неявное приведение типа, если это преобразование безопасно", т. е. не сопряжено с потерей данных; пример - преобразование из Int32 в Int64. Однако для потенциально небезопасного преобразования С# требует явного приведения типа. Помимо приведения, компилятор знает и о другой особенности элементарных типов: к ним применима литеральная форма записи, например:
Console.WriteLine(123.ToString( ) + 456.ToString( )); // "123456"
Проверяемые и непроверяемые операции для элементарных типов
Программистам должно быть хорошо известно, что многие арифметические операции над элементарными типами могут привести к переполнению:
Byte b = 100;
b = (Byte) (b + 200); // После этого Ь равно 44.
В CLR есть IL-команды, позволяющие компилятору по-разному реагировать на переполнение. Так, суммирование двух чисел выполняет команда add, не реагирующая на переполнение, и команда add.ovf, которая при переполнении генерирует исключение System.OverflowException. Кроме того, в CLR есть аналогичные IL-команды для вычитания (sub/sub.ovf), умножения (mul/mul.ovf) и преобразования данных (conv/conv. ovf).
В C# по умолчанию проверка переполнения отключена. Это значит, что компилятор генерирует для операций сложения, вычитания, умножения и преобразования IL-команды без проверки переполнения. Чтобы включить управление процессом обработки переполнения на этапе компиляции, добавьте в командную строку компилятора переключатель /checked. Он сообщает компилятору, что для выполнения сложения, вычитания, умножения и преобразования должны быть сгенерированы IL-команды с проверкой переполнения. Однако программистам вряд ли подойдет установка режима проверки переполнения по всему коду. У них должна быть возможность самим решать, как реагировать на переполнение в каждом случае. И С# предлагает такой механизм гибкого управления проверкой в виде операторов checked и unchecked. Например (предполагается, что компилятор по умолчанию создает код без проверки):
Byte b = 100;
b = checked((Byte) (b + 200)); // Генерируется OverflowException.
Здесь b и 200 преобразуются в 32-разрядные числа и суммируются; результат равен 300. Затем преобразование 300 в Byte генерирует исключение OverflowExcepti on. Если приведение к Byte вывести из оператора checked, исключения не будет.
b = (Byte) checked(b + 200); // b содержит 44; нет OverflowException
Наряду с операторами checked и unchecked, в С# есть одноименные инструкции, позволяющие включить проверяемые или непроверяемые выражения внутрь блока:
checked { // Начало проверяемого блока.
Byte b = 100;
b = (Byte) (b + 200); // Это выражение проверяется на переполнение. } // Конец проверяемого блока,
Установка режима контроля переполнения не влияет на работу метода, вызываемого внутри оператора или инструкции checked, так как действие оператора (и инструкции) checked распространяется только на выбор IL-команд сложения, вычитания, умножения и преобразования сложения.
Используя checked и unchecked, учитывайте следующее.
• Включите в блок checked ту часть кода, в которой при переполнении должно генерироваться исключение.
Включите в блок unchecked ту часть кода, в которой переполнение не должно вызывать исключения. В таком коде переполнение должно возникать "бесшумно".
Документ
Категория
Разное
Просмотров
31
Размер файла
28 Кб
Теги
понкратов, оопип
1/--страниц
Пожаловаться на содержимое документа