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

8.11Операторы checked и unchecked

Операторы checked и unchecked используются для управления контекстом контроля переполнения в арифметических операциях и преобразованиях целых типов.

оператор_checked: checked блок

оператор_unchecked: unchecked блок

Оператор checked задает вычисление всех выражений в блоке в проверяемом контексте, а оператор unchecked задает вычисление всех выражений в блоке в непроверяемом контексте.

Операторы языка checked и unchecked в точности эквивалентны операторам выражений checked и unchecked (§7.6.12), только они применяются к блокам, а не к выражениям.

8.12Оператор lock

Оператор lock устанавливает взаимоисключающую блокировку для заданного объекта, выполняет оператор языка и затем снимает блокировку.

оператор_lock: lock ( выражение ) внедренный_оператор

Выражение оператора lock должно представлять значение, тип которого точно является ссылочным_типом. Для выражения оператора lock никогда не выполняется неявное преобразование с упаковкой (§6.1.7); использование выражения для представления значения, тип которого является типом_значения, вызывает ошибку времени компиляции.

Оператор lock следующего вида:

lock (x) ...

где x — выражение ссылочного_типа, в точности эквивалентен записи

System.Threading.Monitor.Enter(x); try { ... } finally { System.Threading.Monitor.Exit(x); }

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

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

Не рекомендуется блокировать объекты System.Type для синхронизации доступа к статическим данным. Этот же тип может быть заблокирован другим кодом, что приведет к взаимоблокировке. Синхронизировать доступ к статическим данных лучше путем блокировки закрытого статического объекта. Пример:

class Cache { private static readonly object synchronizationObject = new object();

public static void Add(object x) { lock (Cache.synchronizationObject) { ... } }

public static void Remove(object x) { lock (Cache.synchronizationObject) { ... } } }

8.13Оператор using

Оператор using получает один или несколько ресурсов, выполняет заданный оператор языка и затем удаляет ресурсы.

оператор_using: using ( выделение_ресурса ) внедренный_оператор

получение_ресурса: объявление_локальной_переменной выражение

Ресурс — это класс или структура, реализующая интерфейс System.IDisposable, который состоит из одного метода без параметров с именем Dispose. Код, использующий ресурс, может вызвать метод Dispose, чтобы показать, что ресурс больше не нужен. Если не вызывать метод Dispose, ресурс будет в итоге удален автоматически в результате сборки мусора.

Если выделение_ресурса задано как объявление_локальной_переменной, то типом объявления_локальной_переменной должен быть тип dynamic или тип, допускающий неявное преобразование в System.IDisposable. Если выделение_ресурса задано как выражение, то это должно быть выражение типа, допускающего неявное преобразование в System.IDisposable.

Локальные переменные, объявленные при выделении_ресурса, доступны только на чтение и должны включать инициализатор. Если внедренный оператор пытается изменить эти локальные переменные (путем присваивания или с помощью операторов ++ и ‑‑), получить их адрес или передать их как параметры ref или out, возникает ошибка времени компиляции.

Процесс оператора using состоит из трех частей: выделение ресурса, использование и удаление. Использование ресурса неявно включается в оператор try с предложением finally. Это предложение finally удаляет ресурс. Если выделяется ресурс null, метод Dispose не вызывается и исключение не генерируется. Если ресурс имеет тип dynamic, это означает, что он динамически преобразован путем неявного динамического преобразования (§6.1.8) к IDisposable в процессе выделения с целью обеспечения успешного преобразования перед использованием и удалением.

Оператор using в виде

using (ResourceType resource = expression) statement

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

{ ResourceType resource = expression; try { statement; } finally { ((IDisposable)resource).Dispose(); } }

Если же ResourceType является обнуляемым типом значения или ссылочным типом (за исключением dynamic), оператор развертывается следующим образом:

{ ResourceType resource = expression; try { statement; } finally { if (resource != null) ((IDisposable)resource).Dispose(); } }

В противном случае, если ResourceType является типом dynamic, оператор развертывается так:

{ ResourceType resource = expression; IDisposable d = (IDisposable)resource; try { statement; } finally { if (d != null) d.Dispose(); } }

В обоих случаях переменная resource доступна только для чтения во внедренном операторе, а переменная d недоступна и невидима для внедренного оператора.

В реализации разрешается выполнять реализацию определенного оператора using иным образом (например, для повышения быстродействия), при условии сохранения поведения, совместимого с вышеописанным развертыванием.

Оператор using в виде

using (expression) statement

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

Если выделение_ресурса задано в виде объявления_локальной_переменной, можно выделить несколько ресурсов данного типа. Оператор using в виде

using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) statement

в точности эквивалентен последовательности вложенных операторов using:

using (ResourceType r1 = e1) using (ResourceType r2 = e2) ... using (ResourceType rN = eN) statement

В следующем примере создается файл log.txt и в него записываются две строки текста. Затем тот же файл открывается для чтения, и содержащиеся в нем строки текста выводятся на консоль.

using System; using System.IO;

class Test { static void Main() { using (TextWriter w = File.CreateText("log.txt")) { w.WriteLine("This is line one"); w.WriteLine("This is line two"); }

using (TextReader r = File.OpenText("log.txt")) { string s; while ((s = r.ReadLine()) != null) { Console.WriteLine(s); }

} } }

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

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