Лично я использую оператор C # «using» как можно чаще, но есть несколько конкретных вещей, которые я делаю вместе с ним, чтобы избежать потенциальных упомянутых проблем. Для иллюстрации:
void doSomething()
{
using (CustomResource aResource = new CustomResource())
{
using (CustomThingy aThingy = new CustomThingy(aResource))
{
doSomething(aThingy);
}
}
}
void doSomething(CustomThingy theThingy)
{
try
{
// play with theThingy, which might result in exceptions
}
catch (SomeException aException)
{
// resolve aException somehow
}
}
Обратите внимание, что я разделяю выражение "using" на один метод, а использование объекта (ов) - на другой метод с помощью блока "try" / "catch". Я могу вложить несколько «использующих» операторов, подобных этим, для связанных объектов (иногда я углубляюсь в мой рабочий код на три-четыре).
В моих Dispose()
методах для этих пользовательских IDisposable
классов я ловлю исключения (но НЕ ошибки) и регистрирую их (используя Log4net). Я никогда не сталкивался с ситуацией, когда любое из этих исключений могло бы повлиять на мою обработку. Потенциальным ошибкам, как обычно, разрешено распространяться вверх по стеку вызовов и обычно завершать обработку с соответствующим сообщением (ошибка и трассировка стека).
Если бы я как-то столкнулся с ситуацией, когда во время Dispose()
могло произойти значительное исключение, я бы изменил дизайн для этой ситуации. Честно говоря, я сомневаюсь, что это когда-нибудь случится.
Между тем, преимущества и возможности "использования" делают его одной из моих самых любимых функций в C #. Кстати, я работаю на Java, C # и Python в качестве своих основных языков, с множеством других, добавленных сюда и там, и «использование» - одна из моих самых любимых языковых возможностей, потому что это практичная, повседневная рабочая лошадка .