最近看其他人写的C#代码,异常抛出的方式格式各样。总结了三种方式及其优劣:

  1. throw

    try
    {
            do_something();
    }
    catch
    {
            throw;
    }

    这种方式是将原先的异常再次抛出(rethrow),且不会重置异常的堆栈信息(在原先的堆栈信息上增加了当前的异常信息)。是最为推荐的异常抛出方式。

  2. throw new Exception(...)

    try
    {
            do_something();
    }
    catch (Exception ex)
    {
            throw Exception("exception", ex);
    }

    这种异常抛出方式是将原先的异常经过包装后再抛出,将原先的异常放在新异常的内部异常堆栈中(ex.InnerException
    PS: 下面异常抛出方式不要使用!!,没有任何异常信息。

    try
    {
            do_something();
    }
    catch (Exception ex)
    {
            throw Exception("exception");
    }
  3. throw ex

    try
    {
            do_something();
    }
    catch (Exception ex)
    {
            throw ex;
    }

    这种异常抛出方式重置了堆栈信息,不要使用!

测试

代码

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();
            }
        }
    }
}

结果

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
Last modification:August 16, 2018
If you think my article is useful to you, please feel free to appreciate