在c#中重新引发异常时?

在c#中重新引发异常时?,c#,exception,C#,Exception,我已经读过为什么我们需要抛出一个异常并重新抛出它。但我不知道什么时候重新抛出一个异常?我在CalculationOperationNotSupportedException捕获中添加了一个示例,之后,我比较了堆栈跟踪与重试和未重试。这与99%相同,但当您重新引用异常时,它只会添加位置。 当然,如果你能准确地跟踪两个堆栈。第35行是“抛出”位置号,第28行是int result=calculator.Calculate(number1,number2,operation); 我认为在这里不重新刷新

我已经读过为什么我们需要抛出一个异常并重新抛出它。但我不知道什么时候重新抛出一个异常?我在CalculationOperationNotSupportedException捕获中添加了一个示例,之后,我比较了堆栈跟踪与重试和未重试。这与99%相同,但当您重新引用异常时,它只会添加位置。 当然,如果你能准确地跟踪两个堆栈。第35行是“抛出”位置号,第28行是int result=calculator.Calculate(number1,number2,operation); 我认为在这里不重新刷新堆栈跟踪更好。你觉得怎么样

堆栈跟踪而不重新刷新(抛出)我对其进行了评论。

在控制台Calculator.Calculator.Calculation(Int32 number1,Int32 数字2,字符串操作)输入 C:\Users\Behnam\Desktop\C-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Calculator.cs:line 在中的ConsoleCalculator.Program.Main(字符串[]参数)处25 C:\Users\Behnam\Desktop\C-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Program.cs:line 二十八

在catch中使用rethrow堆栈跟踪(CalculationOperationNotSupportedException ex)

在C:\Users\Behnam\Desktop\C-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Calculator.cs中的ConsoleCalculator.Calculator(Int32 number1,Int32 number2,字符串操作)处进行计算(第25行) 在C:\Users\Behnam\Desktop\C-sharp-error-handling-exceptions\06\demos\after\03UsingExceptions\ConsoleCalculator\Program.cs中的ConsoleCalculator.Program.Main(字符串[]参数)处:第35行



我经常链接两篇关于主题的文章。我认为它们是必读的。

基本上,如果无法处理异常,则不应捕获异常。但有时,你必须对任何关于例外的规则做出例外(没有双关语的意思)。您可能需要捕获更广泛的异常,然后将“捕获并释放”应用于您得到的额外异常。例如,以下是我的atempt在重新给特里帕施硅时的表现:

//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;
}

不,你对投掷和再投掷的理解是不正确的

当您抛出一个异常时,您丢失了在新抛出异常之前发生的所有堆栈跟踪信息。问题是,您的所有代码都在同一个文件中,并且您在读取和正确比较每个stacktrace中的信息时遇到困难

构建以下代码,确保每个类都位于不同的.cs文件中。运行它并比较两个打印的堆栈跟踪,您将看到抛出会丢失信息:

//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

    //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