операторы using могут инициализировать переменные вызовами, отличными от конструкторов. Например:
using (Foo f = GetFoo())
{
...
}
Здесь f
может легко быть нулевым, тогда как вызов конструктора никогда не может 1 вернуть ноль. Вот почему оператор using
проверяет на ничтожность. Это не связано с тем, что находится внутри самого блока, потому что оператор using
сохраняет исходное начальное значение. Если вы напишите:
Stream s;
using (s = File.OpenRead("foo.txt"))
{
s = null;
}
тогда поток все равно будет ликвидирован. (Если переменная объявлена в части инициализатора оператора using
, она все равно доступна только для чтения.)
В вашем случае, поскольку вы знаете, что c
не равен нулю, прежде чем войти в блок try
, вам не нужно проверять наличие нуля в блоке finally
, если вы не переназначаете его значение ( что я искренне надеюсь, что вы не!) в блоке.
Теперь с вашим текущим кодом равен небольшой риск того, что асинхронное исключение может возникнуть между присваиванием c
и входом в блок try
- но такого рода гонки трудно избежать условие полностью, так как после завершения конструктора может возникнуть асинхронное исключение, но до того, как значение будет присвоено c
вообще. Я бы предположил, что большинству разработчиков не нужно беспокоиться о подобных вещах - асинхронные исключения имеют тенденцию быть достаточно «сложными», чтобы они все равно остановили процесс.
Есть ли причина, по которой вы все равно не хотите просто использовать оператор using? Если честно, я очень редко пишу свои finally
блоки в эти дни ...
1 См. Ответ Марка и плач. Хотя обычно не актуально.