Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
12
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

17.5Атрибуты для взаимодействия

Примечание. Этот раздел применим только для реализации Microsoft .NET языка C#.

17.5.1Взаимодействие с компонентами com и Win32

Исполняющая среда .NET предоставляет большое число атрибутов, позволяющих программам C# взаимодействовать с компонентами, написанными с использованием модели COM и библиотек DLL Win32. Например, атрибут DllImport можно использовать для метода static extern, чтобы указать, что реализацию метода следует искать в библиотеке DLL Win32. Эти атрибуты находятся в пространстве имен System.Runtime.InteropServices, а подробную документацию на эти атрибуты можно найти в документации исполняющей среды .NET.

17.5.2Взаимодействие с другими языками .Net

17.5.2.1Атрибут IndexerName

Индексаторы реализованы в .NET с помощью индексированных свойств и имеют имя в метаданных .NET. Если атрибут IndexerName отсутствует для индексатора, по умолчанию используется имя Item. Атрибут IndexerName позволяет разработчику переопределить это значение по умолчанию и задать другое имя.

namespace System.Runtime.CompilerServices.CSharp { [AttributeUsage(AttributeTargets.Property)] public class IndexerNameAttribute: Attribute { public IndexerNameAttribute(string indexerName) {...}

public string Value { get {...} } } }

18.Небезопасный код

Базовый язык C#, как определено в предыдущих главах, заметно отличается от C и C++ тем, что в нем не используются указатели в качестве типа данных. Вместо этого C# предоставляет ссылки и возможность создавать объекты, управляемые сборщиком мусора. Эта разработка в сочетании с другими особенностями делает язык C# гораздо более безопасным, чем C и C++. В базовом языке C# просто невозможно иметь неинициализированную переменную, «висящий» указатель или выражение, индексирующее массив за пределами его границ. Таким образом устраняются целые категории ошибок, регулярно досаждающих в программах на C и C++.

Хотя практически у каждой конструкции с типом указателя в C или C++ имеется аналог ссылочного типа в C#, тем не менее в некоторых ситуациях доступ к типам указателей становится необходимостью. Например, согласование с операционной системой, доступ к устройству, сопоставленному памяти, или реализация критического по времени алгоритма могут оказаться неосуществимыми без доступа к указателям. Для удовлетворения этой потребности C# предоставляет возможность писать небезопасный код.

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

Небезопасный код в действительности является «безопасной» возможностью с точки зрения как разработчиков, так и пользователей. Небезопасный код должен быть явно помечен модификатором unsafe, так что разработчик не может случайно использовать небезопасные возможности, а механизм выполнения обеспечивает невозможность выполнения небезопасного кода в ненадежной среде.

18.1Небезопасные контексты

Небезопасные возможности C# доступны только в небезопасных контекстах. Небезопасный контекст вводится включением модификатора unsafe в объявление типа или члена, или использованием небезопасного_оператора:

  • объявление класса, структуры, интерфейса или делегата может включать модификатор unsafe, в этом случае все текстовое пространство этого объявления (включая тело класса, структуры или интерфейса) считается небезопасным контекстом;

  • объявление поля, метода, свойства, события, индексатора, оператора, конструктора экземпляров, деструктора или статического конструктора может включать модификатор unsafe, в этом случае все текстовое пространство этого объявления члена считается небезопасным контекстом;

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

Соответствующие грамматические расширения показаны ниже. Многоточиями (...) для краткости представлены порождения, описанные в предыдущих главах.

модификатор_класса: ... unsafe

модификатор_структуры: ... unsafe

модификатор_интерфейса: ... unsafe

модификатор_делегата: ... unsafe

модификатор_поля: ... unsafe

модификатор_метода: ... unsafe

модификатор_свойства: ... unsafe

модификатор_события: ... unsafe

модификатор_индекса: ... unsafe

модификатор_оператора: ... unsafe

модификатор_конструктора: ... unsafe

объявление_деструктора: атрибутынеобязательно externнеобязательно unsafeнеобязательно ~ идентификатор ( ) тело_деструктора атрибутынеобязательно unsafeнеобязательно externнеобязательно ~ идентификатор ( ) тело_деструктора

модификаторы_статического_конструктора: externнеобязательно unsafeнеобязательно static unsafeнеобязательно externнеобязательно static externнеобязательно static unsafeнеобязательно unsafeнеобязательно static externнеобязательно static externнеобязательно unsafeнеобязательно static unsafeнеобязательно externнеобязательно

внедренный_оператор: ... оператор_unsafe

оператор_unsafe: unsafe блок

В примере

public unsafe struct Node { public int Value; public Node* Left; public Node* Right; }

модификатор unsafe, указанный в объявлении структуры, делает все текстовое пространство объявления структуры небезопасным контекстом. Таким образом можно объявить поля Left и Right с типом указателя. Этот пример можно было бы записать так:

public struct Node { public int Value; public unsafe Node* Left; public unsafe Node* Right; }

Здесь модификаторы unsafe в объявлениях полей делают эти объявления небезопасными контекстами.

Кроме установления небезопасного контекста, дающего возможность использования типов указателей, модификатор unsafe не влияет на тип или член. В этом примере

public class A { public unsafe virtual void F() { char* p; ... } }

public class B: A { public override void F() { base.F(); ... } }

модификатор unsafe метода F в классе A просто делает текстовое пространство F небезопасным контекстом, в котором можно использовать небезопасные возможности языка. В переопределении F в классе B нет необходимости вновь задавать модификатор unsafe, если, конечно, в самом методе F в классе B не требуются небезопасные возможности.

Ситуация несколько другая, когда тип указателя является частью подписи метода

public unsafe class A { public virtual void F(char* p) {...} }

public class B: A { public unsafe override void F(char* p) {...} }

Здесь, поскольку подпись F включает тип указателя, его можно записать только в небезопасном контексте. Однако небезопасный контекст можно ввести либо сделав небезопасным весь класс, как в случае A, либо включив модификатор unsafe в объявление метода, как в случае B.

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