2012-04-17 2 views
16

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

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? 
    } 

Как показать пользователь, если соппы не открываемые или сгенерированные какое-то ошибка?

+0

Surround с блоком TryCatch. – SimpleVar

+0

С 'try/catch'. – Jon

+0

Не могли бы вы уточнить свой вопрос? конечно, что вы просите здесь. – Tejs

ответ

8

using не предлагает никаких бэкдоров в catch.

Просто не развернуть его вручную (нет смысла в том, чтобы Попробовать/поймать внутри с помощью ИМО):

SqlConnection conn = null; 

try 
{ 
    conn = new SqlConnection(""); 
} 
catch ... 
{ 

} 
finally 
{ 
    if (conn != null) 
     conn.Dispose(); 
} 

Я предпочитаю это более чем оборачивать using в try-catch или встраивание в using большую часть в try-catch чтобы избежать появления кода с вложенным try-catch после компиляции. Однако, если вам нужно всего лишь покрыть очень небольшое подмножество большого фрагмента кода в пределах using, я бы стал более гранулированным и вставлял его.

+0

@marc_s Семантика, дело в том, что 'using' не предлагает никакой поддержки, вам нужно вернуться к try/catch. –

+2

@marc_s Мой способ скомпилирует только одну попытку/уловку, в противном случае каждый может самостоятельно. Шахта предлагает не меньшую поддержку, чем «использование». –

22

Там нет ничего особенного кода, написанного внутри 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 блока и обеспечить надлежащую утилизацию самостоятельно (как Адам, предложенный в его ответ).

+0

Почему мы используем try/catch внутри? –

+5

+1 ... это не только не специальная, но даже хорошая практика, чтобы использовать try/catch в инструкции using. Утилизация объектов и обработки исключений - это разные понятия. –

+2

@Raj Потому что Try/Catch - это то, как вы поймаете Исключение. A Использование - это только Try/finally (без улова). Если ваш вопрос заключается в том, почему он не находится за пределами использования, это связано с тем, что создание соединения вряд ли вызовет ошибку, открыв его. – Servy

2

Это точно так же, как и без него.

using(SqlConnection conn = new SqlConnection(connString)) 
{ 
    try{ 
    //some code 
    } 
    catch(SqlException e) 
    MessageBox.Show(e.Message); 
} 
3

Просто в обычном порядке:

Либо

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 
    }     
} 
+0

Какой смысл использовать Try/Catch внутри? –

+2

@Widor: Это не будет обрабатываться, если исключение вызывается в 'SqlConnection conn = new ...' – xbonez

+0

Ну, это зависит от того, что вы там делаете - возможно, вы хотите поймать другое потенциальное исключение (не связанное с SQL) например. – Widor

0

Вы не делаете его внутри 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? 
}  
+0

Вы можете написать try/catch внутри использования. Я верю! –

+1

Вы можете, но не поймать исключение в использовании экземпляра – Jodrell

+0

@Jodrell Но SqlConnection обычно не генерирует исключение в своем конструкторе. Единственное исключение, которое вы, вероятно, получите, - это выражение для параметра. – Servy

8
class SqlConnection 
{ 
    using(sqlConnection) 
    { 

    } 
} 

class Consumer 
{ 
    try 
    { 

    } 
    catch(SqlException) 
    { 

    } 

} 

Это зависит от потребителя класса, чтобы решить, что делать с исключением.

6

Как уже сообщалось, просто добавьте обычную попытку/уловку.

Однако я хотел бы добавить, что это неправильно место, чтобы положить, что попробовать/поймать, особенно если ваша цель «показать пользователям» сообщение. Пусть исключение произойдет на этом уровне и позволит ему создать пузырьку стека для кода, который находится в лучшем положении, чтобы знать, как реагировать на него.

Другими словами, оставьте свой образец кода таким, какой он есть. Не добавляйте ничего нового ... к этому методу. Но, возможно, код, который вызывает этот метод, должен думать о том, как обрабатывать исключение ... любое исключение ... из базы данных.

+0

Можете ли вы показать мне пример этого? Или любую ссылку, которой это достаточно. Благодаря! –

+0

@Raj Проверьте мой ответ. Вот что я упомянул в своем ответе. – Sandeep

-2

Рекомендуется использовать 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 
       } 
     } 

Теперь, если исключение происходит при выполнении некоторых задач внутри с помощью заявления, оба примера иметь такие же результаты. Простой ответ - нет, причина ???

Если исключение встречается в примере 1, оно захватывается блоком catch, не доходя до конца используемого блока. Следовательно, someObject в примере 1 не будет правильно настроен. Даже если CLR щедрый (на который вы не должны рассчитывать) - память, используемая someObject в примере 1, не будет восстановлена ​​(или максимум она будет в коллекции GC Generation 2 GC).

Если в случае примера 2 блок catch находится внутри оператора using. Это означает, что выполнение достигнет конца используемого блока. Таким образом, ваш объект будет удален, и вам не придется беспокоиться об утечке памяти (порча,

+4

Это неправильно. Если при использовании происходит ошибка, объектd будет удаляться неявным блоком 'finally'' using', и исключение будет управляться внешним 'catch'. Во втором случае исключение будет управляться внутренним блоком 'catch', а неявное' finally' 'use' будет утилизировать его позже. Таким образом, единственное отличие состоит в том, что во втором примере «catch» объект все еще доступен, поэтому вы все равно можете использовать его для обработки исключения. В первом примере объект будет больше недоступен в блоке catch. Больше никаких различий. – JotaBe

0

Когда вы вставляете блок using() внутри try/catch, блок using() действительно гарантирует, что Dispose Если не управляемый код внутри вашего используемого блока генерирует исключение, использование() будет просто его употреблять, и оно не достигнет вашего улова. Используйте try/catch внутри блока using(), пропустите с помощью() и попробуйте/try/catch /, или используйте нечетный синтаксис using() try() try с блоком catch (который оставляет вас с нечетным числом скобок и, вероятно, смущает черт из программистов среднего уровня, которые позже сталкиваются с это