Назначение
CTS и CLS служат для обеспечения совместимости, возможности взаимодействия и интеграции различных языков.
Общая система типов CTS
Поскольку в среде .NET все языки рассматриваются как равные, класс, написанный на С#, должен быть эквивалентен классу, написанному на VВ.NET, а интерфейс, определенный в управляемом С++, должен быть полностью аналогичен интерфейсу, определенному в управляемом Коболе. Языки должны договориться о значениях этих концепций перед тем, как смогут взаимодействовать друг с другом. Чтобы воплотить в реальность языковую интеграцию, фирма Мiсrоsоft определила общую систему типов, которой должен придерживаться любой язык в .NET. Мы выделим общие типы, имеющие одинаковую концептуальную семантику в любом языке среды .NET. Microsoft .NET поддерживает богатый набор типов, но мы ограничим наше обсуждение самыми важными из них, в частности размерными типами, ссылочными типами, классами, интерфейсами и делегатами.
Структура базовых типов
CLR поддерживает две различных категории типов: размерные типы и ссылочные типы. Размерные типы (value types) представляют значения, расположенные в стеке. Они не могут быть пустыми(null) и обязаны содержать какие-то данные. Такие данные передаются в функцию по значению, т. е. перед выполнением функции создается копия этого значения. Из этого следует, что исходное значение не меняется, независимо от того, что происходит с его копией в процессе вызова функции. Общая структура типов отражена на рис. 1.1. Заметьте, что все типы наследуются от одного типа Type.
Рис. 1.1. Структура базовых типов .NET
Размерные типы
Переменные размерного типа содержат само значение, а не ссылку на него.
Размерные типы включают примитивы, структуры и перечисления. Примеры приведены в следующем листинге С#:
int i; // примитив struct Point { int х, у } // структура enum State { Off=1, Оn=2 } // перечисление |
Ссылочные типы
Хотя ссылочные типы требуют значительных ресурсов памяти, ссылочный тип предоставляет преимущества по сравнению с размерным. Ссылочные типы (reference types) (в том числе объекты, интерфейсы и указатели) называются так, потому что содержат ссылки на объекты, расположенные в куче, и могут иметь пустое значение (null). Эти типы передаются по ссылке, т.е. когда вы передаете такай объект в функцию, передается адрес или указатель на объект, а не копия объекта, как в случае размерного типа. Поскольку передается ссылка, вызывающая сторона увидит, что вызванная функция сделала с вашим объектом. Первое преимущества состоит в там, что ссылочный тип может использоваться как выходной параметр, а второе - в том, что не тратятся лишние ресурсы, т. к. не создается копия объекта. Если ваш объект велик (занимает большой объем памяти), ссылочные типы являются лучшим выбором. В .NET один из недостатков ссылочного типа заключается в том, что память для него выделяется в управляемой куче, поэтому требуется больше тактов процессора, т. к. CLR должна управлять и осуществлять сборку мусора для этого объекта.
Ссылочные типы включают классы, интерфейсы, массивы и делегаты; их при меры показаны в следующем листинге на С#:
class Саr{…} // класс interface ISteering{…} // интерфейс int[] а = new int[5]; // массив delegate void Process(…); // делегат |
Поддержка размерных типов включена в Мiсrоsоft .NET в целях повышения производительности, однако все в .NET в конечном счете является объектом. На самом деле все примитивные типы имеют соответствующие классы в .NET Framework. Например, int представляет собой псевдоним System.Int32, а System.Int32 оказывается производным от System.ValueType, т. е. это размерный тип. Размерные типы по умолчанию располагаются в стеке, но они всегда могут быть преобразованы в ссылочный тип, располагающийся в куче, и эта операция называется упаковкой (boxing). Следующий фрагмент кода показывает, как упаковать копию значения переменной i:
int i = 1; //i – размерный тип object Ьох = i; //box – ссылочный тип |
Операцией, обратной упаковке, естественно, является распаковка (unboxing), которая представляет собой преобразование объекта ссылочного типа, расположенного в куче, в эквивалентный ему размерный тип, как показано ниже:
int j = (int)box; |
Классы, свойства, индексаторы
CLR предоставляет полноценную поддержку концепций объектно-ориентированного программирования (инкапсуляции, наследования и полиморфизма) и возможностей классов (методов, полей, статических членов, видимости, доступности, вложенных типов и т. п.). Кроме того, CLR поддерживает новые возможности, отсутствующие во многих традиционных объектно-ориентированных языках программирования, включая свойства, индексаторы и события.
Особенности классов:
- нет множественного наследования
- нет аналога шаблонов (в версии 1.1)
Свойства похожи на поля (переменные-члены), за исключением того, что для них имеются методы-установщики (setters) и методы-получатели (getters), как показано ниже:
using System; public class Car { private string make; public string Make { get { return make; } set { make = value; } } public static void Main() { Саr с = new Саr(); c.Make = “Acura”; // используется установщик String s = c.Make; // используется получатель Console.WriteLine(s); } } |
Сходный со свойством синтаксически, индексатор аналогичен конструкции operator[] в С++, т. к. позволяет осуществлять доступ к содержимому объекта подобно обращению к массиву. Другими словами, индексатор позволяет обращаться к объекту так, как будто это обращение к массиву, что показано в следующем примере:
using System; public class Саг { Саг() { wheels = new string[4]; } private string[] wheels; public string this[int index] { get { return wheels[ index]; } set { wheels[index] = value; } } public static void Main() { Саr с = new Саr(); с[0] = “LеftWhееl”; // с[О] может быть как с правой, так \ // и с левой стороны присваивания Console.WriteLine(c[O]); } } |
Делегаты
Одним из наиболее мощных средств языка С является его поддержка указателей на функции. Указатели на функции позволяют создавать программное обеспечение с обработчиками, которые могут быть реализованы кем-то другим. Действительно, указатели на функции позволяют многим людям создавать расширяемое и настраиваемое программное обеспечение. Мiсrоsоft .NET поддерживает типизированную версию указателей на функции, называемых делегатами (delegates).
using System; class TestDelegate { // 1. Определяем прототип для обратного вызова delegate void MsgHandler(string strMsg); // 2. Определяем метод обратного вызова void OnMsg(string strMsg) { Console.WriteLine(strMsg); } public static void Main() { TestDelegate t = new TestDelegate(); // З. Привязка вашего метода обратного вызова MsgHandler f = new MsgHandler(t.OnMsg); // 4. Неявный вызов метода обратного вызова f("Hello, Delegate. "); } } |
Модификаторы доступа и атрибуты типов
К описанию переменной можно добавить следующие модификаторы, служашие для указания дополнительных параметров переменной (для C#):
Модификатор | Описание |
new | переменная скрывает унаследованную переменную с той же сигнатурой. |
public | переменная доступна отовсюду как поле типа, к которому она принадлежит. |
protected | метод доступен из данного класса и из производного от него. |
internal | переменная доступна только из той же программы. |
private | переменная доступна только из типа, где она определена. |
static | статическое поле. |
readonly | после инициализации значение изменить нельзя. |
const | константа (толко примитивный тип). |
protected internal | переменная доступна из текущей программы или из производных типов. |
Модификатор | Описание |
new | метод скрывает унаследованный метод с той же сигнатурой. |
public | метод доступен извне класса. |
protected | метод доступен из данного класса и из производного от него. |
internal | метод доступен только из той же программы. |
private | метод доступен только из класса, где он определён. |
static | метод не предназначен для работы с экземпляром данного класса. |
virtual | метод должен быть переопределён в производном классе. |
abstract | виртуальный метод, определяющий только сигнатуру (без реализации). |
override | метод переопределяет унаследованный виртуальный метод. |
sealed | метод перекрывает унаследованный виртуальный метод, но не может быть перекрыт классами, которые не являются производными от данного (использовать с override). |
extern | метод реализован вне программы. |
Задача среды .NET состоит в такой поддержке языковой интеграции, чтобы программы можно было писать на любом языке, и при этом они могли бы взаимодействовать друг с другом, пользуясь всеми преимуществами наследования, полиморфизма, обработки исключений и другими возможностями. Однако языки созданы неодинаковыми, и разные языки поддерживают разные возможности. Например, С++ чувствителен к регистру, а VB.NET - нет. Чтобы составить из всего этого единое произведение, Мiсrоsоft опубликовала спецификацию Common Language Specification (CLS). В CLS определен набор базовых правил, обязательных для языковой интеграции.
Комментариев нет:
Отправить комментарий