Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 抛出和抛出新异常()之间的差异_C# - Fatal编程技术网

C# 抛出和抛出新异常()之间的差异

C# 抛出和抛出新异常()之间的差异,c#,C#,两者的区别是什么 try { ... } catch{ throw } 及 不管第二个是否显示消息?抛出重新引用原始异常并保留其原始堆栈跟踪 throw-ex抛出原始异常,但重置堆栈跟踪,销毁所有堆栈跟踪信息,直到catch块 永远不要写throw-ex 抛出新异常(例如消息)更糟糕。它创建一个全新的异常实例,丢失异常的原始堆栈跟踪及其类型。(例如,IOException)。 此外,某些异常包含附加信息(例如,ArgumentException.ParamName)。 抛出新异常(例如消

两者的区别是什么

try { ... }
catch{ throw } 


不管第二个是否显示消息?

抛出重新引用原始异常并保留其原始堆栈跟踪

throw-ex
抛出原始异常,但重置堆栈跟踪,销毁所有堆栈跟踪信息,直到
catch


永远不要写
throw-ex

抛出新异常(例如消息)更糟糕。它创建一个全新的
异常
实例,丢失异常的原始堆栈跟踪及其类型。(例如,
IOException
)。
此外,某些异常包含附加信息(例如,
ArgumentException.ParamName
)。
抛出新异常(例如消息)也将销毁此信息

在某些情况下,您可能希望将所有异常包装在自定义异常对象中,以便提供有关抛出异常时代码所做操作的附加信息


为此,定义一个继承
Exception
的新类,以及一个可选的附加构造函数,该构造函数接受
InnerException
以及附加信息,并抛出新的异常类,将
ex
作为
InnerException
参数传递。通过传递原始
InnerException
,可以保留原始异常的所有属性,包括堆栈跟踪。

throw
重新抛出捕获的异常,保留堆栈跟踪,而
throw new exception
会丢失捕获的异常的一些详细信息

您通常会单独使用
throw
来记录异常,而不会在此时完全处理它


BlackWasp有一篇标题足够好的文章。

throw
用于重新引发捕获的异常。如果您想在将异常传递到调用链之前处理它,这将非常有用


使用不带任何参数的
throw
会保留调用堆栈以进行调试。

抛出新异常会吹走当前堆栈跟踪

抛出
将保留原始堆栈跟踪,并且几乎总是更有用。该规则的例外情况是,您希望将该例外情况包装到自己的自定义例外情况中。然后你应该做:

catch(Exception e)
{
    throw new CustomException(customMessage, e);
}

如果需要,可以抛出新异常,将原始异常设置为内部异常。

第一个异常保留原始堆栈跟踪:

try { ... }
catch
{
    // Do something.
    throw;
}
第二个选项允许您更改异常和/或消息和其他数据的类型:

try { ... } catch (Exception e)
{
    throw new BarException("Something broke!");
}
还有第三种方法可以传递内部异常:

try { ... }
catch (FooException e) {
    throw new BarException("foo", e);
} 
我建议使用:

  • 如果您希望在错误情况下执行一些清理,而不销毁信息或添加有关错误的信息,则第一种方法是
  • 如果要添加有关错误的更多信息,请单击第三个按钮
  • 如果要隐藏信息(对不受信任的用户),则第二个选项

第二个示例将重置异常的堆栈跟踪。第一种方法最准确地保留了异常的起源。此外,您还打开了原始类型的包装,这是了解实际错误的关键。。。如果功能需要第二个,例如添加扩展信息或使用特殊类型(如自定义“HandleableException”)重新包装,则只需确保也设置了InnerException属性

最重要的区别是第二个表达式删除了异常类型。异常类型在捕获异常时起着至关重要的作用:

public void MyMethod ()
{
    // both can throw IOException
    try { foo(); } catch { throw; }
    try { bar(); } catch(E) {throw new Exception(E.message); }
}

(...)

try {
    MyMethod ();
} catch (IOException ex) {
    Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
    Console.WriteLine ("Other error");    // [2]
}

如果
foo()
抛出
IOException
[1]
catch块将捕获异常。但是当
bar()
抛出
IOException
时,它将被转换为普通的
异常
ant不会被
[1]
捕获块捕获。

我没有看到任何人提出的另一点:

如果在catch{}块中没有执行任何操作,那么尝试一下……catch是没有意义的。我一直看到这一点:

try 
{
  //Code here
}
catch
{
    throw;
}
或者更糟:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw ex;
}
最糟糕的是:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw new System.Exception(ex.Message);
}

throw或throw ex都用于抛出或重新抛出异常,当您只需记录错误信息而不想将任何信息发送回调用方时,只需将错误记录在catch中并离开即可。但是,如果您想向使用throw或throw-ex的调用方发送有关异常的一些有意义的信息,那么throw和throw-ex之间的区别在于throw保留堆栈跟踪和其他信息,但throw-ex创建了一个新的异常对象,因此原始堆栈跟踪丢失。
因此,我们应该在什么时候使用throw和throw e,在一些情况下,您可能希望重新抛出异常,比如重置调用堆栈信息。例如,如果方法位于库中,并且您希望对调用代码隐藏库的详细信息,则不一定希望调用堆栈包含库中私有方法的信息。在这种情况下,您可以捕获库的公共方法中的异常,然后重新引用它们,以便调用堆栈从这些公共方法开始

投掷;重新显示原始异常并保留异常类型

抛出新异常();重新显示原始异常类型并重置异常堆栈跟踪


掷骰子;重置异常堆栈跟踪并重置异常类型

此处的答案均未显示差异,这可能有助于努力理解差异的人们。考虑这个示例代码:

using System;
using System.Collections.Generic;

namespace ExceptionDemo
{
   class Program
   {
      static void Main(string[] args)
      {
         void fail()
         {
            (null as string).Trim();
         }

         void bareThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw;
            }
         }

         void rethrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw e;
            }
         }

         void innerThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw new Exception("outer", e);
            }
         }

         var cases = new Dictionary<string, Action>()
         {
            { "Bare Throw:", bareThrow },
            { "Rethrow", rethrow },
            { "Inner Throw", innerThrow }
         };

         foreach (var c in cases)
         {
            Console.WriteLine(c.Key);
            Console.WriteLine(new string('-', 40));
            try
            {
               c.Value();
            } catch (Exception e)
            {
               Console.WriteLine(e.ToString());
            }
         }
      }
   }
}
使用系统;
使用System.Collections.Generic;
名称空间异常
{
班级计划
{
静态void Main(字符串[]参数)
{
无效失败()
{
(作为字符串为null);
}
无效光掷()
{
尝试
{
失败();
}
捕获(例外)
using System;
using System.Collections.Generic;

namespace ExceptionDemo
{
   class Program
   {
      static void Main(string[] args)
      {
         void fail()
         {
            (null as string).Trim();
         }

         void bareThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw;
            }
         }

         void rethrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw e;
            }
         }

         void innerThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw new Exception("outer", e);
            }
         }

         var cases = new Dictionary<string, Action>()
         {
            { "Bare Throw:", bareThrow },
            { "Rethrow", rethrow },
            { "Inner Throw", innerThrow }
         };

         foreach (var c in cases)
         {
            Console.WriteLine(c.Key);
            Console.WriteLine(new string('-', 40));
            try
            {
               c.Value();
            } catch (Exception e)
            {
               Console.WriteLine(e.ToString());
            }
         }
      }
   }
}
Bare Throw:
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
   at ExceptionDemo.Program.<>c.<Main>g__bareThrow|0_1() in C:\...\ExceptionDemo\Program.cs:line 19
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

Rethrow
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<>c.<Main>g__rethrow|0_2() in C:\...\ExceptionDemo\Program.cs:line 35
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

Inner Throw
----------------------------------------
System.Exception: outer ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
   at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 43
   --- End of inner exception stack trace ---
   at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 47
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64