最近看其他人写的C#代码,异常抛出的方式格式各样。总结了三种方式及其优劣:
-
throw
1 2 3 4 5 6 7 8
try { do_something(); } catch { throw; }
这种方式是将原先的异常再次抛出(rethrow),且不会重置异常的堆栈信息(在原先的堆栈信息上增加了当前的异常信息)。是最为推荐的异常抛出方式。
-
throw new Exception(…)
1 2 3 4 5 6 7 8
try { do_something(); } catch (Exception ex) { throw Exception("exception", ex); }
这种异常抛出方式是将原先的异常经过包装后再抛出,将原先的异常放在新异常的内部异常堆栈中(
ex.InnerException)
PS: 下面异常抛出方式不要使用!!,没有任何异常信息。1 2 3 4 5 6 7 8
try { do_something(); } catch (Exception ex) { throw Exception("exception"); }
-
throw ex
1 2 3 4 5 6 7 8
try { do_something(); } catch (Exception ex) { throw ex; }
这种异常抛出方式重置了堆栈信息,不要使用!
测试
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace ExceptionDemo
{
class Program
{
static void ThrowException1()
{
try
{
Console.WriteLine("throw");
ProduceException();
}
catch (Exception)
{
throw;
}
}
static void ThrowException2()
{
try
{
Console.WriteLine("throw new Exception(\"ProduceException\", ex)");
ProduceException();
}
catch (Exception ex)
{
throw new Exception("ProduceException", ex);
}
}
static void ThrowException3()
{
try
{
Console.WriteLine("throw new Exception(\"ProduceException\")");
ProduceException();
}
catch (Exception ex)
{
throw new Exception("ProduceException");
}
}
static void ThrowException4()
{
try
{
Console.WriteLine("throw ex");
ProduceException();
}
catch (Exception ex)
{
throw ex;
}
}
static int ProduceException()
{
int a = 0;
int b = 1;
return b/a;
}
static void Main(string[] args)
{
var funcList = new List<Action>
{
ThrowException1,
ThrowException2,
ThrowException3,
ThrowException4,
};
foreach (var action in funcList)
{
try
{
action();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine();
Console.WriteLine();
}
}
}
}
结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
throw
System.DivideByZeroException: 尝试除以零。
在 ExceptionDemo.Program.ProduceException() 位置 E:\ExceptionDemo\Program.cs:行号 68
在 ExceptionDemo.Program.ThrowException1() 位置 E:\ExceptionDemo\Program.cs:行号 21
在 ExceptionDemo.Program.Main(String[] args) 位置 E:\ExceptionDemo\Program.cs:行号 83
throw new Exception("ProduceException", ex)
System.Exception: ProduceException ---> System.DivideByZeroException: 尝试除以零。
在 ExceptionDemo.Program.ProduceException() 位置 E:\ExceptionDemo\Program.cs:行号 68
在 ExceptionDemo.Program.ThrowException2() 位置 E:\ExceptionDemo\Program.cs:行号 30
--- 内部异常堆栈跟踪的结尾 ---
在 ExceptionDemo.Program.ThrowException2() 位置 E:\ExceptionDemo\Program.cs:行号 34
在 ExceptionDemo.Program.Main(String[] args) 位置 E:\ExceptionDemo\Program.cs:行号 83
throw new Exception("ProduceException")
System.Exception: ProduceException
在 ExceptionDemo.Program.ThrowException3() 位置 E:\ExceptionDemo\Program.cs:行号 47
在 ExceptionDemo.Program.Main(String[] args) 位置 E:\ExceptionDemo\Program.cs:行号 83
throw ex
System.DivideByZeroException: 尝试除以零。
在 ExceptionDemo.Program.ThrowException4() 位置 E:\ExceptionDemo\Program.cs:行号 60
在 ExceptionDemo.Program.Main(String[] args) 位置 E:\ExceptionDemo\Program.cs:行号 83
结论
| 异常抛出的方式 | 推荐使用 |
|---|---|
throw; |
GOOD |
throw new Exception("msg", ex); |
GOOD |
throw new Exception("msg"); |
BAD |
throw ex; |
BAD |