Checked и unchecked
Операторы checked и unchecked используются для управления контекстом контроля переполненияв арифметических операциях и преобразованиях целых типов. оператор_checked: оператор_unchecked: Оператор checked задает вычисление всех выражений в блоке в проверяемом контексте, а оператор unchecked задает вычисление всех выражений в блоке в непроверяемом контексте. Операторы языка checked и unchecked в точности эквивалентны операторам выражений checked и unchecked (§7.6.12), только они применяются к блокам, а не к выражениям. Lock Оператор lock устанавливает взаимоисключающую блокировку для заданного объекта, выполняет оператор языка и затем снимает блокировку. оператор_lock: Выражение оператора lock должно представлять значение, тип которого точно является ссылочным_типом. Для выражения оператора lock никогда не выполняется неявное преобразование с упаковкой (§6.1.7); использование выражения для представления значения, тип которого является типом_значения;, вызывает ошибку времени компиляции. Оператор lock следующего вида: lock (x)... где x — выражение ссылочного_типа;, в точности эквивалентен записи System.Threading.Monitor.Enter(x); за исключением того, что x вычисляется только один раз. При установленной взаимоисключающей блокировке код, выполняемый в том же потоке выполнения, также может установить и снять блокировку. Однако код, выполняемый в других потоках, не сможет установить блокировку, пока не будет снята данная блокировка. Не рекомендуется блокировать объекты System.Type для синхронизации доступа к статическим данным. Этот же тип может быть заблокирован другим кодом, что приведет к взаимоблокировке. Синхронизировать доступ к статическим данных лучше путем блокировки закрытого статического объекта. Пример: class Cache public static void Add(object x) { public static void Remove(object x) { 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 является обнуляемым типом значения или ссылочным типом (за исключением dynamic), оператор развертывается следующим образом: { В противном случае, если ResourceType является типом dynamic, оператор развертывается так: { В обоих случаях переменная 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) В следующем примере создается файл log.txt и в него записываются две строки текста. Затем тот же файл открывается для чтения, и содержащиеся в нем строки текста выводятся на консоль. using System; class Test using (TextReader r = File.OpenText("log.txt")) { } Поскольку классы TextWriter и TextReader реализуют интерфейс IDisposable, в примере можно использовать оператор using для того, чтобы гарантировать корректное закрытие обрабатываемого файла после операций чтения или записи. Yield Оператор yield используется в блоке итератора (§8.2) для выдачи значения в объект перечислителя (§10.14.4) или в перечислимый объект итератора (§10.14.5), либо для сигнализации об окончании итерации. оператор_yield: yield не является зарезервированным словом; оно приобретает особый смысл только тогда, когда стоит непосредственно перед ключевым словом return или break. В других контекстах yield может использоваться как идентификатор. На использование оператора yield накладывается ряд ограничений. · Использование оператора yield (в любой из двух форм) вне тела_метода, тела_оператора или тела_метода_доступа вызывает ошибку времени компиляции. · Использование оператора yield (в любой из двух форм) внутри анонимной функции вызывает ошибку времени компиляции. · Использование оператора yield (в любой из двух форм) в предложении finally оператора try вызывает ошибку времени компиляции. · Использование оператора yield return в любом месте оператора try, содержащего предложения catch, вызывает ошибку времени компиляции. В следующем примере демонстрируется несколько допустимых и недопустимых способов использования оператора yield. delegate IEnumerable<int> D(); IEnumerator<int> GetEnumerator() { try { D d = delegate { int MyMethod() { Должно существовать неявное преобразование (§6.1) типа выражения оператора yield return в тип выдачи итератора (§10.14.3). Оператор yield return выполняется следующим образом. · Выражение, заданное в операторе, вычисляется, неявно преобразуется к типу yield и присваивается свойству Current объекта перечислителя; · Выполнение блока итератора приостанавливается. Если оператор yield return находится внутри одного или более блоков try, их соответствующие блоки finally не выполняются в это время; · Метод MoveNext объекта перечислителя возвращает true в вызвавшую его программу, тем самым указывая на успешный переход объекта перечислителя к следующему элементу. Следующий вызов метода MoveNext объекта перечислителя возобновляет выполнение блока итератора с того места, где оно было приостановлено. Оператор yield break выполняется следующим образом. · Если оператор yield break входит в один или несколько блоков try, с которыми связаны соответствующие блоки finally, управление вначале передается в блок finally самого внутреннего оператора try. Если управление достигает конечной точки блока finally, после этого управление передается в блок finally следующего объемлющего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены все блоки finally всех объемлющих операторов try. · Управление возвращается в метод, вызвавший блок итератора. Это либо метод MoveNext, либо метод Dispose объекта перечислителя. Поскольку оператор yield осуществляет безусловную передачу управления в другое место, конечная точка оператора yield никогда не будет достижима.
9. Пространства имен; Программы на C# организованы с помощью пространств имен. Пространства имен используются как в качестве «внутренней» системы организации для программы, так и в качестве «внешней» системы организации — способа представления программных элементов, предоставляемых другим программам. Директивы using (§9.4) служат для упрощения использования пространств имен. 9.1 Единицы компиляции; Единица_компиляции; определяет общую структуру исходного файла. Единица компиляции состоит из 0 или более директив_using, за которыми следуют 0 или более глобальных_атрибутов;, за которыми следуют 0 или более объявлений_членов_пространства_имен;. единица_компиляции: Программа на C# состоит из одной или более единиц компиляции, каждая из которых содержится в отдельном исходном файле. При компиляции программы на C# все единицы компиляции обрабатываются совместно. Таким образом, единицы компиляции могут зависеть друг от друга, возможно циклически. Директивы_using единицы компиляции влияют на глобальные_атрибуты; и объявления_членов_пространства_имен; этой единицы компиляции, но не влияют на другие единицы компиляции. Глобальные_атрибуты (§17) единицы компиляции разрешают спецификацию атрибутов для конечной сборки и модуля. Сборки и модули действуют как физические контейнеры для типов. Сборка может состоять из нескольких физически отдельных модулей. Объявления_членов_пространства_имен; каждой единицы компиляции программы размещают члены в одной области объявления, называемой глобальным пространством имен. Например: Файл A.cs: class A {} Файл B.cs: class B {} Эти две единицы компиляции размещаются в одно глобальное пространство имен, в данном случае объявляя два класса с полными именами A и B. Поскольку эти две единицы компиляции размещаются в одну и ту же область объявлений, было бы ошибкой, если бы в каждой из них содержалось объявление члена с одинаковым именем. 9.2 Объявления пространства имен Объявление_пространства_имен состоит из ключевого слова namespace, за которым следует имя и тело пространства имен, а затем точка с запятой (необязательно). объявление_пространства_имен: проверенный_идентификатор: тело_пространства_имен: Объявление_пространства_имен; может быть объявлением верхнего уровня в единице_компиляции; или объявлением члена внутри другого объявления_пространства_имен;. Если объявление_пространства_имен; встречается как объявление верхнего уровня в единице_компиляции;, это пространство имен становится членом глобального пространства имен. Если объявление_пространства_имен; встречается внутри другого объявления_пространства_имен;, внутреннее пространство имен становится членом внешнего пространства имен. В обоих случаях имя пространства имен должно быть уникальным внутри содержаще
|