C#中throw和throw ex的区别 [英] Difference between throw and throw ex in C#

查看:56
本文介绍了C#中throw和throw ex的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 使用系统; 
使用 System.Collections.Generic;
使用 System.Linq;
使用 System.Text;

namespace throwMyDemo
{
class Program
{
静态 void Main( string [] args)
{
RaiseExcption r = new RaiseExcption();
尝试
{
r.Without();
}
catch (MyException ex1)
{
Console.WriteLine(ex1.Message);
Console.WriteLine(ex1.StackTrace);
Console.Read();
}
尝试
{


r.With();
}
catch (MyException ex2)
{
Console.WriteLine(ex2.Message);
Console.WriteLine(ex2.StackTrace);
Console.Read();
Console.Read();
}
}
}
class MyException:异常
{
public MyException(): base ()
{
}

}
class RaiseExcption
{
public void 没有()
{
尝试
{
throw new MyException();
}
catch (MyException me)
{
throw ;
}
}
public void 使用()
{
尝试
{
throw new MyException();
}
catch (MyException me)
{
throw me;
}
}
}
}



我写了这段代码来测试throw和throw ex之间的区别但不幸的是它不起作用。我的意思是说有和没有的堆栈跟踪指向错误位置作为抛出语句而不是指向抛出异常的确切错误位置,即抛出新的MyException()任何人都可以帮我这个。感谢提前

解决方案

当你使用带有空参数的throw时,你将重新抛出最后一个异常。当您抛出现有异常时,您正在创建一个新异常。



有什么区别?简单:堆栈跟踪。

空参数重新抛出并保留现有的堆栈列表,参数化版本创建一个新的堆栈跟踪到throw的点。对于调试,空版本告诉你错误实际发生的位置,参数版本丢弃了。


我没有意识到这种行为并且发现它非常令人惊讶。它看起来好像抛出表现不正确但它不是我们ca如果我们将异常源和catch-rethrow移动到不同的方法中,那就更清楚了。



了解堆栈框架中报告的行号很重要是控制离开方法的点,这可能不是首次抛出异常的点。在catch-rethrow的特殊情况下,堆栈框架行号对应于重新抛出的位置,这发生在 throw throw ex



这是一个简单的程序,演示了行号在堆栈框架内的变化方式。



  class 计划{
静态 void Main( string [] args){
Console.BufferWidth = 160 ;

Console.WriteLine( 间接调用BadMethod而不重新抛出) ;
Console.WriteLine( ***************** **************************);
尝试 {
#line 100
PassThrough();
#line default
} catch (例外e){
Console.WriteLine(E);
}
Console.WriteLine();

Console.WriteLine( 间接调用BadMethod并重新抛出);
Console.WriteLine( ***************** **********************);
尝试 {
#line 200
WithRethrow();
#line default
} catch (例外e){
Console.WriteLine(E);
}
Console.WriteLine();
Console.Read();
}

public static void PassThrough(){
#line 1000
BadMethod();
#line default
}

public < span class =code-keyword> static
void WithRethrow(){
试用 {
#line 2000
BadMethod();
} catch (例外e){
Console.WriteLine(e);
throw ;
}
#line default
}

public static void BadMethod(){
#line 3000
throw new 异常( \MSG:好方法坏了\);
#line default
}
}



奇怪的 #line 指令改变调试信息中保存的行号,并在堆栈跟踪中给出简单的数字。这样做是为了更容易讨论结果。



有两种情况,在这两种情况下我们称之为通过中介抛出BadMethod()的异常,PassThrough( )什么都不做或WithRethrow(),它的名字暗示。



间接调用BadMethod而不重新抛出
***************** **************************
System.Exception:味精:好方法变坏了$ Badbethod()b $ b线路3000
在PassThrough()线1000
在Main(String [] args)线100

间接调用BadMethod并重新抛出
****** *********************************
System.Exception:味精:好方法坏了
at BadMethod()第3000行
at WithRethrow()第2000行
System.Exception:味精:好方法坏了
在BadMethod()第3000行
at WithRethrow()行2003
在Main(String [] args)第200行





如果你可以想象一个异常通过在搜索匹配的catch块的方法然后在PassThrough()中,异常进入并离开相同的行号(1000),并在堆栈框架中报告。



在WithRethro中w()方法异常进入第2000行,但在被捕获并重新抛出之后离开第2003行。在WithRethrow()中获得的堆栈跟踪与Main()中的堆栈跟踪的比较清楚地显示了报告的行号的变化。



这与您的情况完全类似最初描述,即

  public   void  WTFMethod(){
尝试 {
throw 异常();
} catch {
throw ;
}
}





异常被抛出,捕获然后重新抛出,堆栈帧报告点控制离开了方法。因此,虽然看起来很奇怪没有获得异常的正确位置,但是catch和rethrow的行为在整个调用堆栈中是完全一致的。



Alan。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace throwMyDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            RaiseExcption r = new RaiseExcption();
            try
            {
               r.Without();
            }
            catch(MyException ex1)
            {
                Console.WriteLine(ex1.Message);
                Console.WriteLine(ex1.StackTrace);
                Console.Read();
            }
            try
            {

             
                r.With();
            }
            catch (MyException ex2)
            {
                Console.WriteLine(ex2.Message);
                Console.WriteLine(ex2.StackTrace);
                Console.Read();
                Console.Read();
            }
        }
    }
    class MyException : Exception
    {
        public MyException():base()
    {
    }

    }
    class RaiseExcption
    {
        public void Without()
        {
            try
            {
                throw new MyException();
            }
            catch (MyException me)
            {
                throw;
            }
        }
        public void With()
        {
            try
            {
                throw new MyException();
            }
            catch (MyException me)
            {
                throw me;
            }
        }
    }
}


I wrote this code to test the difference between throw and throw ex but unfortunately it is not working. I mean to say that the stack trace for both with and without is pointing the error location as throw statment instead of pointing the exact error location where the exception was thrown ie throw new MyException() "Can any one help me with this. Thanks in advance

解决方案

When you use the throw with an empty parameter, you are re-throwing the last exception. When you throw the existing exception you are creating a new exception.

What's the difference? Simple: the stack trace.
The empty parameter re-throw and keeps the existing stack list, the parametered version creates a new stack trace to the point of the throw. For debugging, the empty version tells you where the error actually occurred, the parametered version discards that.


I was unaware of this behaviour and find it quite suprising. It certainly looks as if throw is behaving incorrectly but it isn't and we can see that more clearly if we move the exception source and the catch-rethrow into different methods.

It is important to understand that the line number reported in a stack frame is the point where control leaves the method and this may not be the point where the exception was first thrown. In the special case of catch-rethrow the stack frame line number corresponds to the position of the rethrow and this happens for both throw and throw ex.

Here is simple program that demonstrates the way that line numbers can change within the stack frame.

class Program {
  static void Main(string[] args) {
    Console.BufferWidth = 160;

    Console.WriteLine("Indirect call of BadMethod with no rethrows");
    Console.WriteLine("*******************************************");
    try {
#line 100
      PassThrough();
#line default
    } catch (Exception e) {
      Console.WriteLine(e);
    }
    Console.WriteLine();

    Console.WriteLine("Indirect call of BadMethod with rethrow");
    Console.WriteLine("***************************************");
    try {
#line 200
      WithRethrow();
#line default
    } catch (Exception e) {
      Console.WriteLine(e);
    }
    Console.WriteLine();
    Console.Read();
  }

  public static void PassThrough() {
#line 1000
    BadMethod();
#line default
  }

  public static void WithRethrow() {
    try {
#line 2000
      BadMethod();
    } catch (Exception e) {
      Console.WriteLine(e);
      throw;
    }
#line default
  }

  public static void BadMethod() {
#line 3000
    throw new Exception("\"MSG: Good method gone bad\"");
#line default
  }
}


The strange #line directives alter the line numbers saved in debug information and give us simple numbers in the stack traces. This was done to make discussion of the results easier.

There are two cases and in the both we call the exception throwing BadMethod() via an intermediary, either PassThrough() which does nothing or WithRethrow() which does what the name suggests.

Indirect call of BadMethod with no rethrows
*******************************************
System.Exception: "MSG: Good method gone bad"
   at BadMethod()          line 3000
   at PassThrough()        line 1000
   at Main(String[] args)  line 100

Indirect call of BadMethod with rethrow
***************************************
System.Exception: "MSG: Good method gone bad"
   at BadMethod()          line 3000
   at WithRethrow()        line 2000
System.Exception: "MSG: Good method gone bad"
   at BadMethod()          line 3000
   at WithRethrow()        line 2003
   at Main(String[] args)  line 200



If you can imagine an exception passing through a method in the search for a matching catch block then in PassThrough() the exception enters and leaves at the same line number (1000) and this is reported in the stack frame.

In the WithRethrow() method the exception enters at line 2000 but leaves at line 2003 after being caught and rethrown. Comparison of the stack trace obtained within WithRethrow() with that from Main() clearly show the change of reported line number.

This is exactly analogous to the situation that you originally described, i.e.

public void WTFMethod() {
  try {
    throw new Exception();
  } catch {
    throw;
  }
}



The exception is thrown, caught and then rethrown and the stack frame reports the point where control left the method. So although it looks very odd not to get the correct location for the exception, the behaviour for a catch and rethrow is completely consistent through the whole call stack.

Alan.


这篇关于C#中throw和throw ex的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆