Захват исключений внутри Использование оператора
Я знаю, что Использование инструкции предоставляет объект, который создается. Например, если бы я хотел сделать что-то вроде этого:
Using(SqlConnection conn = new SqlConnection(connString))
{
//some code
//How to show the users if conn is not opened up or generated some kind of error?
}
Как показать пользователям, если conn не открывается или не генерирует какую-либо ошибку?
Ответы
Ответ 1
Нет ничего особенного в коде, написанном внутри блока using
- просто используйте try.catch
для обработки исключений:
using(SqlConnection conn = new SqlConnection(connString))
{
try
{
conn.Open();
// do more stuff here......
}
catch(SqlException sqlEx)
{
// log error and possibly show to user in a MessageBox or something else
}
}
Сам блок using(...) { ... }
сконструирован только, чтобы гарантировать, что ресурс/объект, который он "инкапсулирует", правильно утилизируется, когда он больше не нужен. Вы ничего не можете сделать с помощью оператора using
, чтобы он обрабатывал ошибки.
Итак, если вы ожидаете, что просто создание объекта может потерпеть неудачу, вам придется поместить весь блок using
внутри блока try ... catch
или вернуться к блоку try ... catch ... finally
и обеспечить правильное удаление самостоятельно ( как предложил Адам в своем ответе).
Ответ 2
using
не предлагает никаких бэкдоров в catch
.
Просто раскройте его вручную (нет смысла использовать try/catch внутри IMO):
SqlConnection conn = null;
try
{
conn = new SqlConnection("");
}
catch ...
{
}
finally
{
if (conn != null)
conn.Dispose();
}
Я предпочитаю, чтобы обертывание using
в try-catch
или вложение try-catch
в using
большую часть времени, чтобы избежать того, чтобы код завершился с вложенным try-catch
после компиляции. Если вам нужно всего лишь покрыть очень маленькое подмножество большого фрагмента кода в using
, я бы стал более гранулированным и вставлял его.
Ответ 3
class SqlConnection
{
using(sqlConnection)
{
}
}
class Consumer
{
try
{
}
catch(SqlException)
{
}
}
Решать, что делать с исключением, зависит от потребителя класса.
Ответ 4
Как указывали другие ответы, просто добавьте обычный try/catch.
Однако я бы добавил, что это место неправильное, чтобы помещать этот try/catch, особенно если ваша цель - "показать пользователям" сообщение. Пусть исключение происходит на этом уровне и позволяет ему пузыриться в стеке, чтобы закодировать его в лучшем положении, чтобы знать, как реагировать на него.
Другими словами, оставьте свой образец кода таким, какой он есть. Не добавляйте ничего нового... к этому методу. Но, возможно, код, который вызывает этот метод, должен думать о том, как обрабатывать исключение... любое исключение... из базы данных.
Ответ 5
Просто в обычном режиме:
Либо
try
{
using(SqlConnection conn = new SqlConnection(connString))
{
//some code
}
}
catch (Exception exc)
{
//handle error
}
или
using(SqlConnection conn = new SqlConnection(connString))
{
try
{
//some code
}
catch (Exception exc)
{
//handle error
}
}
Ответ 6
Это точно так же, как и вы.
using(SqlConnection conn = new SqlConnection(connString))
{
try{
//some code
}
catch(SqlException e)
MessageBox.Show(e.Message);
}
Ответ 7
Вы не делаете этого внутри using
try
{
using(SqlConnection conn = new SqlConnection(connString))
{
// Some code for when "conn" is succesfully instantiated
}
}
catch (SomeSpecificConnectionInstantiationException ex)
{
// Use ex to handle a bizarre instantiation exception?
}
Ответ 8
Когда вы внедряете блок using() внутри try/catch, блок using() действительно гарантирует, что Dispose вызывается. Однако, если не управляемый код в любом месте вашего используемого блока генерирует исключение, использование() будет просто его употреблять, и оно не достигнет вашего улова. Используйте try/catch внутри блока using(), пропустите с помощью() и сделайте try/catch/finally или используйте нечетный синтаксис using() try с блоком catch (который оставляет вас с нечетным числом скобок и скорее всего, смутит черт из программистов среднего уровня, которые позже столкнутся с ним.
Ответ 9
Рекомендуется использовать try {} catch() {} внутри оператора using, если вы хотите поймать исключение, созданное кодом внутри блока использования. Теперь рассмотрим следующие два примера - это объясняет, почему блок try-catch внутри оператора using является хорошей практикой.
Пример 1
try{
using(SomeObject so = new SomeObject){
// Perform some tasks
}
}catch(SomeException objSomeException){
// Perform some actions, if exception occurs
}
Пример 2
using(SomeObject so = new SomeObject){
try{
// Perform some tasks
}catch(SomeException objSomeException){
// Perform some actions, if exception occurs
}
}
Теперь, если исключение возникает при выполнении некоторых задач внутри оператора using, оба примера будут иметь одинаковые результаты. Простой ответ - нет, причина???
Когда в примере 1 возникает исключение, оно захватывается блоком catch - без достижения конца используемого блока. Следовательно, someObject в примере 1 не будет правильно настроен. Даже если CLR щедрый (на который вы не должны рассчитывать) - память, используемая someObject в примере 1, не будет восстановлена (или максимум она будет в коллекции GC Generation 2 GC).
Если в случае примера 2 блок catch находится внутри оператора using. Это означает, что выполнение достигнет конца используемого блока. Поэтому ваш объект будет удален, и вам не придется беспокоиться об утечке памяти (порча,