Есть такой необычный оператор, который я пропустил, - 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);
}