Отчет по практике по ТРИЗБД в работе с языками C# и Visual basic. Отчет по практике. Оглавление 1 Изм. Лист докум. Подп. Дата 1 Проверил Гатауллина Ф. Ф. 1
Скачать 1.49 Mb.
|
Структура языка программирования C#Элементы языка программирования C#Члены class могут быть *статическ--ими членами* или *членами экземпляра*. Статические члены принадлежат классу в целом, а члены экземпляра принадлежат конкретным объектам (экземплярам классов). Ниже перечислены виды членов, которые могут содержаться в классе. *Константы**. Константные значения, связанные с классом.*Constants**: Constant values associated with the class Поля. Переменные, связанные с классом. Методы. Действия, которые может выполнять класс. Свойства. Действия, связанные с чтением и записью именованных свойств класса. Индексаторы. Действия, реализующие индексирование экземпляров класса, чтобы обращаться к ним как к массиву. События. Уведомления, которые могут быть созданы этим классом. Операторы. Поддерживаемые классом операторы преобразования и выражения. Конструкторы. Действия, необходимые для инициализации экземпляров класса или класса в целом. Методы завершения. Действия, выполняемые перед окончательным удалением экземпляров класса. Типы. Вложенные типы, объявленные в классе. Возможности доступаКаждый член класса имеет определенный уровень доступности. Он определяет, из какой области программы можно обращаться к этому члену. Существует шесть уровней доступности. Ниже приведены модификаторы доступа. public. Доступ не ограничен. private. Доступ возможен только из этого класса. protected. Доступ возможен из этого класса и из классов, производных от него. internal. Доступ ограничен текущей сборкой (.exe или .dll). protected internal. Доступ ограничен данным классом, классами, производными от данного класса, либо классами в той же сборке. private protected. Доступ ограничен данным классом либо классами, производными от данного типа в той же сборке. ПоляПоле является переменной, связанной с определенным классом или экземпляром класса. Поле, объявленное с модификатором static, является статическим. Статическое поле определяет строго одно место хранения. Независимо от того, сколько будет создано экземпляров этого класса, существует только одна копия статического поля. Поле, объявленное без модификатора static, является полем экземпляра. Каждый экземпляр класса содержит отдельные копии всех полей экземпляра, определенных для этого класса. В следующем примере каждый экземпляр класса Color содержит отдельную копию полей экземпляра R, G и B, но для каждого из статических полей Black, White, Red, Green и Blue существует только одна копия: public class Color { public static readonly Color Black = new Color(0, 0, 0); public static readonly Color White = new Color(255, 255, 255); public static readonly Color Red = new Color(255, 0, 0); public static readonly Color Green = new Color(0, 255, 0); public static readonly Color Blue = new Color(0, 0, 255); public byte R; public byte G; public byte B; public Color(byte r, byte g, byte b) { R = r; G = g; B = b; } } Как показано в предыдущем примере, можно объявить поля только для чтения, используя модификатор readonly. Присвоение значения доступному только для чтения полю может происходить только при объявлении этого поля или в конструкторе этого класса. МетодыМетод — это член, реализующий вычисление или действие, которое может выполнять объект или класс. Доступ к статическим методам осуществляется через класс. Доступ к методам экземпляра осуществляется через экземпляр класса. Для метода можно определить список параметров, которые представляют передаваемые методу значения или ссылки на переменные. Методы имеют возвращаемый тип, который задает тип значения, вычисляемого и возвращаемого методом. Если метод не возвращает значение, для него устанавливается тип возвращаемого значения void. Как и типы, методы могут иметь набор параметров типа, для которых при вызове метода необходимо указывать аргументы типа. В отличие от типов, аргументы типа зачастую могут выводиться из аргументов вызова метода, и тогда их не обязательно задавать явным образом. Сигнатура метода должна быть уникальной в пределах класса, в котором объявлен этот метод. Сигнатура метода включает имя метода, количество параметров типа, а также количество, модификаторы и типы параметров метода. Сигнатура метода не включает тип возвращаемого значения. Если тело метода является одиночным выражением, метод можно определить с помощью компактного формата выражения, как показано в следующем примере: public override string ToString() => "This is an object"; ПараметрыПараметры позволяют передать в метод значения или ссылки на переменные. Фактические значения параметрам метода присваиваются на основе аргументов, заданных при вызове метода. Существует четыре типа параметров: параметры значения, ссылочные параметры, параметры вывода и массивы параметров. Параметр значения используется для передачи входных аргументов. Параметр значения сопоставляется с локальной переменной, которая получит начальное значение из значения аргумента, переданного в этом параметре. Изменения параметра значения не влияют на аргумент, переданный для этого параметра. Параметры значения можно сделать необязательными, указав для них значения по умолчанию. Тогда соответствующие аргументы можно не указывать. Ссылочный параметр используется для передачи аргументов по ссылке. Аргумент, передаваемый ссылочному параметру, должен являться переменной с определенным значением. При выполнении метода ссылочный параметр указывает на то же место хранения, где размещена переменная аргумента. Чтобы объявить ссылочный параметр, используйте модификатор ref. Следующий пример кода демонстрирует использование параметров ref. static void Swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } public static void SwapExample() { int i = 1, j = 2; Swap(ref i, ref j); Console.WriteLine($"{i} {j}"); // "2 1" } Параметр вывода используется для передачи аргументов по ссылке. Он похож на ссылочный параметр, однако не требует явно присваивать значение аргумента, предоставляемого вызывающим объектом. Чтобы объявить параметр вывода, используйте модификатор out. В следующем примере показано использование параметров out с помощью синтаксиса, появившегося в C# 7. static void Divide(int x, int y, out int result, out int remainder) { result = x / y; remainder = x % y; } public static void OutUsage() { Divide(10, 3, out int res, out int rem); Console.WriteLine($"{res} {rem}"); // "3 1" } Массив параметров позволяет передавать в метод переменное число аргументов. Чтобы объявить массив параметров, используйте модификатор params. Массив параметров может быть только последним параметром в методе. Для него можно использовать только тип одномерного массива. В качестве примера правильного использования массива параметров можно назвать методы Write и WriteLine, реализованные в классе System.Console. Ниже представлены объявления этих методов. ublic class Console { public static void Write(string fmt, params object[] args) { } public static void WriteLine(string fmt, params object[] args) { } // ... } Внутри метода массив параметров полностью идентичен обычному параметру типа массив. Но зато при вызове метода, использующего массив параметров, ему можно передать либо один аргумент типа массив, либо любое количество аргументов типа элемент для массива параметров. В последнем случае экземпляр массива автоматически создается и инициализируется с заданными аргументами. Код из этого примера int x, y, z; x = 3; y = 4; z = 5; Console.WriteLine("x={0} y={1} z={2}", x, y, z); ...эквивалентен следующей конструкции: int x = 3, y = 4, z = 5; string s = "x={0} y={1} z={2}"; object[] args = new object[3]; args[0] = x; args[1] = y; args[2] = z; Console.WriteLine(s, args); Тело метода и локальные переменные Тело метода содержит инструкции, которые будут выполнены при вызове метода. В теле метода можно объявлять переменные, относящиеся к выполнению этого метода. Такие переменные называются локальными переменными. В объявлении локальной переменной нужно указать имя типа и имя переменной. Также можно задать ее начальное значение. Следующий пример кода объявляет локальную переменную i с нулевым начальным значением, и еще одну локальную переменную j без начального значения. class Squares { public static void WriteSquares() { int i = 0; int j; while (i < 10) { j = i * i; Console.WriteLine($"{i} x {i} = {j}"); i = i + 1; } } } C# требует, чтобы локальной переменной было явно присвоено значение, прежде чем можно будет получить это значение. Например, если в предложенное выше объявление i не включить начальное значение, компилятор сообщит об ошибке при последующем использовании i, так как для i нет явно присвоенного значения. Метод может использовать инструкцию return, чтобы вернуть управление вызывающему объекту. Если метод возвращает void, инструкции return не могут указывать выражение. В методе, выходное значение которого имеет любой другой тип, инструкции return должны содержать выражение, которое вычисляет возвращаемое значение. Статические методы и методы экземпляра Метод, объявленный с модификатором static, является статическим методом. Статический метод не работает с конкретным экземпляром и может напрямую обращаться только к статическим членам. Метод, объявленный с модификатором static, является методом экземпляра. Метод экземпляра работает в определенном экземпляре и может обращаться как к статическим методам, так и к методам этого экземпляра. В методе можно напрямую обратиться к экземпляру, для которого этот метод был вызван, используя дескриптор this. Использование ссылки на this в статическом методе является недопустимым. Следующий класс Entity содержит статические члены и члены экземпляра. class Entity { static int s_nextSerialNo; int _serialNo; public Entity() { _serialNo = s_nextSerialNo++; } public int GetSerialNo() { return _serialNo; } public static int GetNextSerialNo() { return s_nextSerialNo; } public static void SetNextSerialNo(int value) { s_nextSerialNo = value; } } Каждый экземпляр Entity содержит серийный номер (и может содержать другие данные, которые здесь не показаны). Конструктор объекта Entity (который рассматривается как метод экземпляра) задает для нового экземпляра следующий доступный серийный номер. Поскольку конструктор является членом экземпляра, он может обращаться как к полю экземпляра _serialNo, так и к статическому полю s_nextSerialNo. Статические методы GetNextSerialNo и SetNextSerialNo могут обращаться к статическому полю s_nextSerialNo, но прямое обращение из них к полю экземпляра _serialNo приводит к ошибке. В приведенном ниже примере показано использование класса Entity. Entity.SetNextSerialNo(1000); Entity e1 = new Entity(); Entity e2 = new Entity(); Console.WriteLine(e1.GetSerialNo()); // Outputs "1000" Console.WriteLine(e2.GetSerialNo()); // Outputs "1001" Console.WriteLine(Entity.GetNextSerialNo()); // Outputs "1002" Статические методы SetNextSerialNo и GetNextSerialNo вызываются для класса, а метод экземпляра GetSerialNo вызывается для экземпляров класса. Виртуальные, переопределяющие и абстрактные методыЕсли объявление метода экземпляра включает модификатор virtual, такой метод называется виртуальным методом. Если модификатор virtual отсутствует, метод считается невиртуальным. При вызове виртуального метода могут быть вызваны разные его реализации в зависимости от того, какой тип среды выполнения имеет экземпляр, для которого вызван этот метод. При вызове невиртуального метода решающим фактором является тип во время компиляции для этого экземпляра. Виртуальный метод можно переопределить в производном классе. Если объявление метода экземпляра содержит модификатор override, этот метод переопределяет унаследованный виртуальный метод с такой же сигнатурой. Объявление виртуального метода создает новый метод. Переопределение этого метода создает специализированный виртуальный метод с новой реализацией. Абстрактным методом называется виртуальный метод без реализации. Абстрактный метод объявляется с модификатором abstract. Его можно объявить только в абстрактном классе. Абстрактный метод должен обязательно переопределяться в каждом производном классе, не являющемся абстрактным. Следующий пример кода объявляет абстрактный класс Expression, который представляет узел дерева выражений, а также три производных класса: Constant, VariableReference и Operation, которые реализуют узлы дерева выражений для констант, ссылок на переменные и арифметических операций. (Этот пример похож на типы дерева выражений, но не связан с ними.) public abstract class Expression { public abstract double Evaluate(Dictionary } public class Constant : Expression { double _value; public Constant(double value) { _value = value; } public override double Evaluate(Dictionary { return _value; } } public class VariableReference : Expression { string _name; public VariableReference(string name) { _name = name; } public override double Evaluate(Dictionary { object value = vars[_name] ?? throw new Exception($"Unknown variable: {_name}"); return Convert.ToDouble(value); } } public class Operation : Expression { Expression _left; char _op; Expression _right; public Operation(Expression left, char op, Expression right) { _left = left; _op = op; _right = right; } public override double Evaluate(Dictionary { double x = _left.Evaluate(vars); double y = _right.Evaluate(vars); switch (_op) { case '+': return x + y; case '-': return x - y; case '*': return x * y; case '/': return x / y; default: throw new Exception("Unknown operator"); } } } Четыре приведенных выше класса можно использовать для моделирования арифметических выражений. Например, с помощью экземпляров этих классов выражение x + 3 можно представить следующим образом. Expression e = new Operation( new VariableReference("x"), '+', new Constant(3)); Метод Evaluate экземпляра Expression вызывается для вычисления данного выражения и создает значение double. Этот метод принимает аргумент Dictionary, который содержит имена переменных (в качестве ключей записей) и значения переменных (в качестве значений записей). Так как Evaluate — абстрактный метод, то в неабстрактных классах, производных от Expression, необходимо переопределить Evaluate. В Constant реализация метода Evaluate просто возвращает хранимую константу. В VariableReference реализация этого метода выполняет поиск имени переменной в словаре и возвращает полученное значение. В Operation реализация этого метода сначала вычисляет левый и правый операнды (рекурсивно вызывая их методы Evaluate), а затем выполняет предоставленную арифметическую операцию. В следующей программе классы Expression используются для вычисления выражения x * (y + 2) с различными значениями x и y. Expression e = new Operation( new VariableReference("x"), '*', new Operation( new VariableReference("y"), '+', new Constant(2) ) ); Dictionary vars["x"] = 3; vars["y"] = 5; Console.WriteLine(e.Evaluate(vars)); // "21" vars["x"] = 1.5; vars["y"] = 9; Console.WriteLine(e.Evaluate(vars)); // "16.5" Перегрузка методовПерегрузка метода позволяет использовать в одном классе несколько методов с одинаковыми именами, если они имеют уникальные сигнатуры. Когда при компиляции встречается вызов перегруженного метода, компилятор использует принцип разрешения перегрузки, чтобы определить, какой из методов следует вызвать. Разрешение перегрузки выбирает из методов тот, который лучше всего соответствует предоставленным аргументам. Если не удается выбрать конкретный подходящий метод, возвращается ошибка. В следующем примере показано, как работает разрешение перегрузки. Комментарий к каждому вызову метода UsageExample указывает, какой именно метод вызывается. class OverloadingExample { static void F() => Console.WriteLine("F()"); static void F(object x) => Console.WriteLine("F(object)"); static void F(int x) => Console.WriteLine("F(int)"); static void F(double x) => Console.WriteLine("F(double)"); static void F static void F(double x, double y) => Console.WriteLine("F(double, double)"); public static void UsageExample() { F(); // Invokes F() F(1); // Invokes F(int) F(1.0); // Invokes F(double) F("abc"); // Invokes F F((double)1); // Invokes F(double) F((object)1); // Invokes F(object) F F(1, 1); // Invokes F(double, double) } Как видно из этого примера, вы всегда можете выбрать конкретный метод, явным образом приведя типы аргументов к соответствующим типам параметров и аргументам типов. Другие функции-членыВсе члены класса, содержащие исполняемый код, совокупно называются функции-члены. В предыдущем разделе описаны основные варианты методов, используемых в качестве функций-членов. В этом разделе описываются другие типы функций-членов, поддерживаемые в языке C#: конструкторы, свойства, индексаторы, события, операторы и методы завершения. В следующем примере показан универсальный класс с именем MyList public class MyList { const int DefaultCapacity = 4; T[] _items; int _count; public MyList(int capacity = DefaultCapacity) { _items = new T[capacity]; } public int Count => _count; public int Capacity { get => _items.Length; set { if (value < _count) value = _count; if (value != _items.Length) { T[] newItems = new T[value]; Array.Copy(_items, 0, newItems, 0, _count); _items = newItems; } } } public T this[int index] { get => _items[index]; set { _items[index] = value; OnChanged(); } } public void Add(T item) { if (_count == Capacity) Capacity = _count * 2; _items[_count] = item; _count++; OnChanged(); } protected virtual void OnChanged() => Changed?.Invoke(this, EventArgs.Empty); public override bool Equals(object other) => Equals(this, other as MyList static bool Equals(MyList { if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null); if (Object.ReferenceEquals(b, null) || a._count != b._count) return false; for (int i = 0; i < a._count; i++) { if (!object.Equals(a._items[i], b._items[i])) { return false; } } return true; } public event EventHandler Changed; public static bool operator ==(MyList Equals(a, b); public static bool operator !=(MyList !Equals(a, b); } КонструкторыC# поддерживает конструкторы экземпляров и статические конструкторы. Конструктор экземпляра является членом, который реализует действия для инициализации нового экземпляра класса. Статический конструктор является членом, который реализует действия для инициализации самого класса при первоначальной его загрузке. Конструктор объявляется в виде метода без возвращаемого типа, имя которого совпадает с именем класса, в котором он определен. Если объявление конструктора содержит модификатор static, объявляется статический конструктор. В противном случае это объявление считается конструктором экземпляра. Конструкторы экземпляров можно перегружать, и для них можно указать необязательные параметры. Например, класс MyList MyList MyList В отличие от других членов, конструкторы экземпляров не наследуются. Класс не имеет конструкторов экземпляров, кроме объявленных в самом этом классе. Если в классе не объявлен конструктор экземпляра, для него автоматически создается пустой конструктор без параметров. СвойстваСвойства естественным образом дополняют поля. И те, и другие являются именованными членами со связанными типами, и для доступа к ним используется одинаковый синтаксис. Однако свойства, в отличие от полей, не указывают места хранения. Вместо этого свойства содержат методы доступа, в которых описаны операторы, выполняемые при чтении или записи значений. Свойство объявляется так же, как поле, за исключением того, что объявление заканчивается не точкой с запятой, а парой разделителей { и }, между которыми указан метод доступа get или set. Свойство, для которого определены акцессоры get и set, является свойством для чтения и записи. Если в свойстве есть только акцессор get, оно является свойством только для чтения, и если только акцессор set — свойством только для записи. Акцессор get оформляется как метод без параметров, у которого тип возвращаемого значения совпадает с типом, установленным для этого свойства. Метод доступа set соответствует методу с одним именованным значением параметра и без возвращаемого типа. Метод доступа get вычисляет значение свойства. Метод доступа set предоставляет новое значение для свойства. При ссылке на свойство в качестве назначения в операторе присваивания или в качестве операнда для ++ или -- вызывается метод доступа set. В остальных случаях при ссылке на свойство вызывается метод доступа get. Класс MyList MyList names.Capacity = 100; // Invokes set accessor int i = names.Count; // Invokes get accessor int j = names.Capacity; // Invokes get accessor Как и в отношении полей и методов, C# поддерживает свойства экземпляра и статические свойства. Статические свойства объявляются с модификатором static, а свойства экземпляра — без него. Акцессоры свойства могут быть виртуальными. Если объявление свойства содержит модификатор virtual, abstract или override, этот модификатор применяется к акцессорам свойства. ИндексаторыИндексатор является членом, позволяющим индексировать объекты так, как будто они включены в массив. Индексатор объявляется так же, как свойство, за исключением того, что именем элемента является this, а за этим именем следует список параметров, находящийся между разделителями [ и ]. Эти параметры доступны в акцессорах индексатора. Как и свойства, можно объявить индексаторы для чтения и записи, только для чтения или только для записи. Кроме того, поддерживаются виртуальные акцессоры индексатора. Класс MyList MyList names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); for (int i = 0; i < names.Count; i++) { string s = names[i]; names[i] = s.ToUpper(); } Индексаторы могут быть перегружены. В одном классе можно объявить несколько индексаторов, если у них различаются количество или типы параметров. ОператорыОператор является членом, который определяет правила применения определенного выражения к экземплярам класса. Вы можете определить операторы трех типов: унарные операторы, двоичные операторы и операторы преобразования. Все операторы объявляются с модификаторами public и static. В классе MyList MyList a.Add(1); a.Add(2); MyList b.Add(1); b.Add(2); Console.WriteLine(a == b); // Outputs "True" b.Add(3); Console.WriteLine(a == b); // Outputs "False" Первый Console.WriteLine выводит True, поскольку два списка содержат одинаковое число объектов с одинаковыми значениями в том же порядке. Если бы в MyList Методы завершенияМетод завершения является членом, который реализует действия для завершения существования экземпляра класса. Как правило, метод завершения необходим для освобождения неуправляемых ресурсов. Методы завершения не могут иметь параметры, не могут содержать модификаторы доступа, и их невозможно вызвать явным образом. Метод завершения для экземпляра вызывается автоматически в процессе сборки мусора. Дополнительные сведения см. в статье о методах завершения. Сборщик мусора имеет широкую степень свободы в выборе времени уничтожения объектов и вызова методов завершения. В частности, время вызова методов завершения не является детерминированным, и эти методы могут выполняться в любом потоке. По этим и некоторым другим причинам методы завершения следует использовать в классах только в крайнем случае, когда невозможны другие решения. Уничтожение объектов лучше контролировать с помощью инструкции using. СобытияСобытие — это член, с помощью которого класс или объект предоставляют уведомления. Объявление события выглядит так же, как объявление поля, но содержит ключевое слово event и обязано иметь тип делегата. В классе, который объявляет член события, это событие действует как обычное поле с типом делегата (если это событие не является абстрактным и не объявляет методы доступа). Это поле хранит ссылку на делегат, который представляет добавленные к событию обработчики событий. Если обработчики событий отсутствуют, это поле имеет значение null. Класс MyList Клиенты реагируют на события посредством обработчиков событий. Обработчики событий можно подключать с помощью оператора += и удалять с помощью оператора -=. Следующий пример кода подключает обработчик события Changed к событию MyList class EventExample { static int s_changeCount; static void ListChanged(object sender, EventArgs e) { s_changeCount++; } public static void Usage() { var names = new MyList<string>(); names.Changed += new EventHandler(ListChanged); names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); Console.WriteLine(s_changeCount); // "3" } } Для более сложных сценариев, требующих контроля над базовым хранилищем события, в объявлении события можно явным образом предоставить методы доступа add и remove. Они будут действовать аналогично методу доступа set для свойства. ВыраженияВыражения создаются из операндов и операторов. Операторы в выражении указывают, какие действия нужно применить к операндам. Примеры операторов: +, -, *, / и new. Операндами могут являться литералы, поля, локальные переменные, выражения и т. п. Если выражение содержит несколько операторов, их приоритет определяет порядок, в котором они оцениваются. Например, выражение x + y * z вычисляется как x + (y * z), поскольку оператор * имеет более высокий приоритет, чем оператор +. Если операнд располагается между двумя операторами с одинаковым приоритетом, порядок их выполнения определяется ассоциативностью операторов. Все бинарные операторы, за исключением операторов объединения со значением NULL и операторов присваивания, являются левоассоциативными, т. е. эти операции выполняются слева направо. Например, выражение x + y + z вычисляется как (x + y) + z. Операторы присваивания, операторы объединения со значением NULL ?? и ??=, а также условный оператор ?: являются правоассоциативными, т. е. эти операции выполняются справа налево. Например, выражение x = y = z вычисляется как x = (y = z). Приоритет и ассоциативность операторов можно изменять, используя скобки. Например, в выражении x + y * z сначала y умножается на z, а результат прибавляется к x, а в выражении (x + y) * z сначала суммируются x и y, а результат умножается на z. Большинство операторов могут быть перегружены. Перегрузка операторов позволяет создать пользовательскую реализацию оператора для таких операций, в которых один или оба операнда имеют определяемый пользователем тип класса или структуры. C# предоставляет несколько операторов для выполнения арифметических, логических операций, побитовых операций и сдвигов, сравнения на равенство и порядок. Полный список операторов C#, упорядоченных по уровню приоритета, см. в статье Операторы C#. ОператорыДействия программы выражаются с помощью операторов. C# поддерживает несколько типов операторов, некоторые из которых определяются как внедренные операторы. С помощью блоков можно использовать несколько операторов в таких контекстах, где ожидается только один оператор. Блок состоит из списка инструкций, заключенных между разделителями { и }. Операторы объявления используются для объявления локальных переменных и констант. Операторы выражений позволяют вычислять выражения. В качестве оператора можно использовать такие выражения, как вызовы методов, выделение объектов с помощью оператора new, назначения с помощью = и составных операторов присваивания, операторы ++ и -- для приращения и уменьшения, а также выражения await. Операторы выбора используются для выбора одного оператора из нескольких возможных вариантов в зависимости от значения какого-либо выражения. Эта группа содержит операторы if и switch. Операторы итерации используются для многократного выполнения внедренного оператора. Эта группа содержит операторы while, do, for и foreach. Операторы перехода используются для передачи управления. Эта группа содержит операторы break, continue, goto, throw, return и yield. Операторы try...catch позволяют перехватывать исключения, создаваемые при выполнении блока кода, а оператор try...finally используется для указания кода завершения, который выполняется всегда, независимо от появления исключений. Операторы checked и unchecked операторы позволяют управлять контекстом проверки переполнения для целочисленных арифметических операций и преобразований. Оператор lock позволяет создать взаимоисключающую блокировку заданного объекта перед выполнением определенных операторов, а затем снять блокировку. Оператор using используется для получения ресурса перед определенным оператором, и для удаления ресурса после его завершения. Ниже перечислены виды операторов, которые можно использовать. Объявление локальной переменной. Объявление локальной константы. Оператор выражений. Оператор if. Оператор switch. Оператор while. Оператор do. Оператор for. Оператор foreach. Оператор break. Оператор continue. Оператор goto. Оператор return. Оператор yield. Операторы throw и try. Операторы checked и unchecked. Оператор lock. Оператор using. |