[英]When Rethrow a Exception in c#?
我已經閱讀了為什么我們需要拋出異常並重新拋出它。 但是我對何時重新拋出異常感到困惑? 我在 CalculationOperationNotSupportedException catch 中放入 throw 時添加了一個示例,之后,我將 Stack Trace 與 Rethrowing 和不 Rethrowing 進行了比較。 99% 都是一樣的,但是當您重新拋出異常時,它只會添加位置。 當然,如果你准確地進行了兩次堆棧跟蹤。 第 35 行是“拋出”位置號,第 28 行是 int result =calculator.Calculate(number1, number2, operation); 我認為不在這里重新拋出的堆棧跟蹤更好。 你怎么看?
Stack Trace without rethrowing(throw) 我評論了它。
在 C:\\Users\\Behnam\\Desktop\\c-sharp-error-handling-exceptions\\06\\demos\\after\\03UsingExceptions\\ConsoleCalculator\\Calculator.cs 中的 ConsoleCalculator.Calculator.Calculate(Int32 number1, Int32 number2, String operation): C:\\Users\\Behnam\\Desktop\\c-sharp-error-handling-exceptions\\06\\demos\\after\\03UsingExceptions\\ConsoleCalculator\\Program.cs:line 28 中的 ConsoleCalculator.Program.Main(String[] args) 中的第 25 行
在 catch 中重新拋出的堆棧跟蹤(CalculationOperationNotSupportedException ex)
在 C:\\Users\\Behnam\\Desktop\\c-sharp-error-handling-exceptions\\06\\demos\\after\\03UsingExceptions\\ConsoleCalculator\\Calculator.cs 中的 ConsoleCalculator.Calculator.Calculate(Int32 number1, Int32 number2, String operation): C:\\Users\\Behnam\\Desktop\\c-sharp-error-handling-exceptions\\06\\demos\\after\\03UsingExceptions\\ConsoleCalculator\\Program.cs:line 35 中的 ConsoleCalculator.Program.Main(String[] args) 中的第 25 行
public int Calculate(int number1, int number2, string operation)
{
string nonNullOperation =
operation ?? throw new ArgumentNullException(nameof(operation));
if (nonNullOperation == "/")
{
try
{
return Divide(number1, number2);
}
catch (ArithmeticException ex)
{
throw new CalculationException("An error occurred during division", ex);
}
}
else
{
throw new CalculationOperationNotSupportedException(operation);
}
}
static void Main(string[] args)
{
var calculator = new Calculator();
int number1=1;
int number2=1;
string operation = "+";
try
{
int result = calculator.Calculate(number1, number2, operation);
DisplayResult(result);
}
catch (CalculationOperationNotSupportedException ex)
{
// Log.Error(ex);
WriteLine(ex);
throw;
}
}
有兩篇關於我經常鏈接的主題的文章。 我認為它們是必讀的。
基本上,如果您無法處理異常,則不應捕獲異常。 但有時,您必須對任何有關 Exception 的規則進行例外處理(沒有雙關語意)。 您可能需要更廣泛地捕捉,然后將“捕捉和釋放”應用於您獲得的額外異常。 例如,這是我嘗試復制 TryParse:
//Parse throws ArgumentNull, Format and Overflow Exceptions.
//And they only have Exception as base class in common, but identical handling code (output = 0 and return false).
bool TryParse(string input, out int output){
try{
output = int.Parse(input);
}
catch (Exception ex){
if(ex is ArgumentNullException ||
ex is FormatException ||
ex is OverflowException){
//these are the exceptions I am looking for. I will do my thing.
output = 0;
return false;
}
else{
//Not the exceptions I expect. Best to just let them go on their way.
throw;
}
}
//I am pretty sure the Exception replaces the return value in exception case.
//So this one will only be returned without any Exceptions, expected or unexpected
return true;
}
不,您對投擲和再投擲的工作原理的理解是錯誤的。
當你拋出一個異常時,你會丟失在新拋出的異常之前發生的所有堆棧跟蹤信息。 問題是您將所有代碼都放在同一個文件中,並且在讀取和正確比較每個堆棧跟蹤中的信息時遇到了麻煩。
構建以下代碼,確保每個類都在不同的 .cs 文件中。 運行它並比較兩個打印的堆棧跟蹤,您將看到 throwing 丟失了信息:
//Foo.cs
public class Foo
{
public void Crash() => throw new Exception();
}
//Blah.cs
public class Blah
{
public void CrashAndThrow()
{
var foo = new Foo();
try
{
foo.Crash();
}
catch (Exception ex)
{
throw ex;
}
}
public void CrashAndReThrow()
{
var foo = new Foo();
try
{
foo.Crash();
}
catch
{
throw;
}
}
}
//Program.cs
class Program
{
static void Main(string[] args)
{
var bla = new Blah();
try
{
bla.CrashAndThrow();
}
catch (Exception ex)
{
Console.WriteLine("Throw:");
Console.WriteLine(ex.StackTrace);
Console.WriteLine();
}
try
{
bla.CrashAndReThrow();
}
catch (Exception ex)
{
Console.WriteLine("Rethrow:");
Console.WriteLine(ex.StackTrace);
}
Console.ReadLine();
}
}
這個程序的輸出是,在我的電腦中:
Throw:
at SOStuff.Alpha.Blah.CrashAndThrow() in ...\SOStuff\Blah.cs:line 16
at SOStuff.Program.Main(String[] args) in ...\SOStuff\Program.cs:line 13
Rethrow:
at SOStuff.Alpha.Foo.Crash() in ...\SOStuff\Foo.cs:line 7
at SOStuff.Alpha.Blah.CrashAndReThrow() in ...\SOStuff\Blah.cs:line 24
at SOStuff.Program.Main(String[] args) in ...\SOStuff\Program.cs:line 24
如您所見,當您拋出時, Foo
拋出的原始異常的所有信息都丟失了。
我適用的一般規則是:
99% 的情況下,我會應用規則 #1。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.