Есть такой необычный оператор, который я пропустил, - using. Этот оператор предназначен для того, чтобы выделить ресурсы, а затем их автоматически освободить.
Пример:
using (R r1 = new R ()) { r1.F(); }
что эквивалентно следующему коду:
R r1 = new R(); try { r1.F(); } finally { if (r1 != null) { ((IDisposable)r1).Dispose(); } }
Здесь класс R должен реализовывать интерфейс IDisposable:
interface IDisposable { void Dispose(); }
Можно перечислять ресурсы через запятую:
using (R r1 = new R(), r2 = new R()) { r1.F(); r2.F(); }
или, что тоже самое:
using (R r1 = new R()) { using (R r2 = new R()) { r1.F(); r2.F(); } }
Иногда бывает удобно заменить имя Dispose на какое-нибудь более подходящие (например "Close"). В этом случае можно сделать Dispose закрытым (private), а метод написать отдельно.
void IDisposable.Dispose () { Dispose(); } public void Close () { freeState(); }
Если захотелось сделать метод Dispose, то возможно используются какие-либо ресурсы OS, поэтому возможно тип должен не уметь маршаллиться или быть MarshalByReference.
Этот оператор может применяться только к типам-ссылкам (reference types, т.е. настоящим объектам). Если применить, к примеру, для переменной типа int, то компилироваться не будет.
lock (obj) { ... }
Это эквивалентно:
System.Threading.Monitor.Enter(obj); try { ... } finally { System.Threading.Monitor.Exit(obj); }
за исключением того, что выражение obj вычисляется один раз, а не два.
Для того, чтобы заблокировать статические переменные нужно использовать класс-типа:
lock (typeof (CustomClassName)) { ... }
Пример
checked (expr) { ... } unchecked (expr) { ... }
эти операторы полезны, когда нужно преобразовать больший тип в меньший, например long в int. Если этого сделать нельзя, кидается OverflowException.
Можно их использовать внутри выражения, например:
class Test { public const int AllBits = unchecked((int)0xFFFFFFFF); public const int HighBit = unchecked((int)0x80000000); }