日期:2014-05-18  浏览次数:20937 次

C#异常传递

? ? 无论写什么方面的程序,异常是不可避免的,而怎么处理涉及的东西则比较多,异常的处理方式,自己的理解分为两个方面的,一种是正常的业务异常,例如银行转帐时金额不够,这类错误一般会直接提示给用户;另一种是系统内部错误,例如银行转帐时,网络中断,这类错误同样也是需要提示给用户,但也是提示系统错误而已,不属于业务异常;无论那种错误,基本都会涉及到异常的捕捉处理和日志记录.现在的系统多属于分层的组件结构,异常更多的是在不同的组件之间传递,所以异常的捕捉和传递也相当重要,很少是由原始的异常发送的地方处理异常.
? ? .net的异常传递处理方式网上有很多规范可以使用,这里不涉及处理异常的顺序或者方式,主要对于异常的传递,典型的处理方式如下:

static void TestException1()
{
    try
    {
        DivideZero();
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
?虽然是同一个异常,他会把异常信息传递给上层,但是会丢失异常真正的堆栈信息,他只会把异常的堆栈定义到当前抛出异常的地方;所以如果需要把原始的异常的堆栈信息抛给上层,则直接使用throw,而不需要任何特殊处理
static void TestException2()
{
    try
    {
        DivideZero();
    }
    catch//catch (Exception)
    {
        throw;
    }
}

? ? 这是网上推荐的做法,实际上,他的确可以把底层的异常堆栈和异常抛给外层,但是在测试的时候,因为自己的不小心,这种方式还是有个小问题,只是平时很容易忽略掉,如果异常的真实发送地点正是在异常处理快里面,而不是异常处理快里面的函数里面,他也会丢失堆栈信息,这和throw ex处理方式没啥分别,具体原因还有待考证.

? ? 测试源代码

namespace ExceptionDemo
{
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            Test(TestException1);
            Test(TestException2);
            Test(TestException3);
            Test(TestException4);
            Console.ReadLine();
        }

        static void Test( Action action)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.WriteLine();
        }

        static void TestException1()
        {
            try
            {
                DivideZero();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        static void TestException2()
        {
            try
            {
                DivideZero();
            }
            catch//catch (Exception)
            {
                throw;
            }
        }

        static void TestException3()
        {
            try
            {
                int a = 0;
                Console.WriteLine(10 / a);
            }
            catch
            {
                throw;
            }
        }

        static void TestException4()
        {
            try
            {
                DivideZero();
            }
            catch (Exception ex)
            {
                throw new Exception("处理出错", ex);
            }
        }

        static void DivideZero()
        {
            int a = 0;
            Console.WriteLine(10 / a);
        }
    }
}

?本地的输出,使用的是vs2008,.net3.5

?

? ? 从上图的红色标记可以看到,即是使用throw,对于代码块里面直接抛出的异常,他一样会丢失相应的堆栈信息.这样看,还是包装一层要安全一点,但是具体原因还不是特别清楚.
?