Захват исключений внутри Использование оператора

Я знаю, что Использование инструкции предоставляет объект, который создается. Например, если бы я хотел сделать что-то вроде этого:

    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. Это означает, что выполнение достигнет конца используемого блока. Поэтому ваш объект будет удален, и вам не придется беспокоиться об утечке памяти (порча,