Разница между повторным бросанием параметра без улова и ничего не делает?
Предположим, что у меня есть два следующих класса в двух разных сборках:
//in assembly A
public class TypeA {
// Constructor omitted
public void MethodA
{
try {
//do something
}
catch {
throw;
}
}
}
//in assembly B
public class TypeB {
public void MethodB
{
try {
TypeA a = new TypeA();
a.MethodA();
}
catch (Exception e)
//Handle exception
}
}
}
В этом случае try-catch в MethodA просто повышает исключение, но не справляется с этим. Есть ли преимущество в использовании try-catch вообще в MethodA? Другими словами, существует ли разница между этим типом блока try-catch и вообще не используется?
Ответы
Ответ 1
В вашем примере это не имеет никакого преимущества. Но бывают случаи, когда желательно просто создать конкретное исключение.
public void Foo()
{
try
{
// Some service adapter code
// A call to the service
}
catch (ServiceBoundaryException)
{
throw;
}
catch (Exception ex)
{
throw new AdapterBoundaryException("some message", ex);
}
}
Это позволяет вам легко определить, к какой границе произошло исключение. В этом случае вам нужно будет обеспечить, чтобы ваши граничные исключения были выбраны только для кода, специфичного для границы.
Ответ 2
Да, есть разница. Когда вы поймаете исключение,.NET предполагает, что вы каким-то образом обработаете его, стек разматывается до функции, выполняющей catch.
Если вы его не поймаете, это станет необработанным исключением, которое вызовет какую-то диагностику (например, отладчик или регистратор исключений), будет доступен полный стек и его состояние в фактической точке сбоя для проверки.
Итак, если вы поймаете, повторите бросок исключения, которое не обрабатывается в другом месте, вы лишаете диагностический инструмент действительно полезной информации о том, что на самом деле произошло.
Ответ 3
Взятый как есть, первый вариант будет казаться плохим (или должен быть "бесполезным"?) идеей. Однако это редко делается так. Исключения повторно выбрасываются из блока Catch обычно в двух условиях:
а. Вы хотите проверить исключение, сгенерированное для данных, и условно вывести его в стек.
try
{
//do something
}
catch (Exception ex)
{
//Check ex for certain conditions.
if (ex.Message = "Something bad")
throw ex;
else
//Handle the exception here itself.
}
б. Недопустимое условие произошло в компоненте, и эта информация должна быть передана вызывающему коду (обычно путем добавления другой полезной информации или ее полной упаковки в другой тип исключения).
try
{
//do something
}
catch (StackOverflowException ex)
{
//Bubble up the exception to calling code
//by wrapping it up in a custom exception.
throw new MyEuphemisticException(ex, "Something not-so-good just happened!");
}
Ответ 4
С кодом, как вы его написали для MethodA, нет никакой разницы. Все, что он будет делать, это съесть процессорные циклы. Однако может быть преимущество в написании кода таким образом, если есть ресурс, который вы должны освободить. Например
Resource r = GetSomeResource();
try {
// Do Something
} catch {
FreeSomeResource();
throw;
}
FreeSomeResource();
Однако нет реального смысла в этом. Было бы лучше просто использовать блок finally.
Ответ 5
Просто ретронирование не имеет смысла - это так же, как если бы вы ничего не делали.
Однако он становится полезным, когда вы на самом деле что-то делаете - наиболее распространенная вещь - регистрировать исключение. Вы также можете изменить состояние своего класса, независимо от того, что.
Ответ 6
Никогда не делайте вариант A. Как говорит Антон, он съедает трассировку стека. Пример JaredPar также поглощает стек. Лучшим решением будет:
SomeType* pValue = GetValue();
try {
// Do Something
} finally {
delete pValue;
}
Если у вас есть что-то в С#, которое нужно отпустить, например FileStream, у вас есть следующие два варианта:
FileStream stream;
try
{
stream = new FileStream("C:\\afile.txt");
// do something with the stream
}
finally
{
// Will always close the stream, even if there are an exception
stream.Close();
}
Или более чисто:
using (FileStream stream = new FileStream("c:\\afile.txt"))
{
// do something with the stream
}
Использование инструкции будет удалять (и закрывать) поток по завершении или когда исключение закрывается.
Ответ 7
Когда вы ловите и бросаете, это позволяет вам установить точку останова в строке throw
.
Ответ 8
Исключения повторного броска могут быть использованы для инкапсуляции в обобщенное исключение, например... рассмотрим следующий пример.
public class XmlException: Exception{
....
}
public class XmlParser{
public void Parse()
{
try{
....
}
catch(IOException ex)
{
throw new XmlException("IO Error while Parsing", ex );
}
}
}
Это дает преимущество перед категоризацией исключений. Так обработчики файлов aspx и многие другие системные коды делают инкапсуляцию исключений, которая определяет их путь до стека и поток логики.
Ответ 9
Блок сборки A - try catch не имеет для меня никакого смысла. Я считаю, что если вы не собираетесь обрабатывать исключение, то почему вы перехватываете эти исключения.. Это было бы все равно брошено на следующий уровень.
Но если вы создаете API-интерфейс среднего уровня или что-то в этом роде и обрабатываете исключение (и, следовательно, есть исключение) в этом слое, это не имеет смысла, тогда вы можете бросить свой собственный класс ApplicationException. Но, безусловно, повторение одного и того же исключения не имеет смысла.
Ответ 10
Поскольку классы находятся в двух разных сборках, вам может понадобиться o просто поймать исключение для его регистрации, а затем выбросить обратно вызывающему, чтобы он мог обрабатывать его так, как он считает нужным. Бросок вместо throw ex сохранит контекстуальную информацию о том, откуда возникло исключение. Это может оказаться полезным, когда ваша сборка является API/фреймворком, где вы никогда не должны проглатывать исключения, если это не имеет смысла делать это, но полезно, тем не менее, при устранении проблем, если он регистрируется, например, в EventLog.
Ответ 11
Вы можете использовать блок try {} catch (ex) {} в методе A, только если вы можете поймать конкретное исключение, которое может обрабатываться в MethodA() (например, для ведения журнала).
Другой вариант - это цепочка исключений с использованием свойства InnerException и передать его вызывающему. Эта идея не будет убивать трассировку стека.