C#准确抛出异常错误位置

上一年,为了最大程度减小影响,提得最多的词是 "精准防控"。程序异常处理也要做到精准,这样才能节约排查时间,降低分析难度,快速解决问题。我们经常使用try-catch捕捉异常,使用StackTrace来输出具体位置。但在复杂的框架和业务系统中,要注意它的使用方式。下面分别以不同的实例来说明问题。

一、单层捕捉异常

业务逻辑非常简单,代码只有一层(不切实际的想象)。

using System;
using System.Windows.Forms;
namespace ExceptionTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                int a = 10;
                int b = 0;
                Console.WriteLine(a / b);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
   }
}

  使用try-catch能轻松捕捉异常位置:17行的b为0,不能当作除数!

二、外层捕捉异常,内层不处理(可用)

实际项目中,往往是对象调用、函数嵌套,为了简便(偷懒),我们在最外层加try-catch,里面不做任何处理。

using System;
using System.Windows.Forms;
namespace ExceptionTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                int a = 10;
                int b = 0;
                Divide(a, b);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        public static void Divide(int a,int b)
        {
            Console.WriteLine(a / b);
        }
    }
}

结果也能居然也能定位,这难道就是"无为而治"吗?

三、外层捕捉异常,内部抛出

为了彰显我们有良好的代码习惯,得在内层函数加个try,显得更复杂,似乎才能体现出"水平"。

using System;
using System.Windows.Forms;
namespace ExceptionTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                int a = 10;
                int b = 0;
                Divide(a, b);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        public static void Divide(int a, int b)
        {
            try
            {
                Console.WriteLine(a / b);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}

结果无法准确定位到29行,而变成了throw所在33行。

四、外层捕捉异常,内层抛出异常

再尝试抛出throw ex看看。

using System;
using System.Windows.Forms;
namespace ExceptionTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                int a = 10;
                int b = 0;
                Divide(a, b);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        public static void Divide(int a, int b)
        {
            try
            {
                Console.WriteLine(a / b);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}

结果还是不能定位。多此一举?

五、外层捕捉异常,内层抛出新异常

 在内层抛出一个新异常。

using System;
using System.Windows.Forms;
namespace ExceptionTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                int a = 10;
                int b = 0;
                Divide(a, b);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        public static void Divide(int a, int b)
        {
            try
            {
                Console.WriteLine(a / b);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}
这是最容易犯的问题,这样就妥妥找不到出错的位置了!

六、外层捕捉异常,内层抛出内部异常(推荐)

我们内层抛出new Exception(且包含内部异常),而不是直接抛出Exception

using System;
using System.Windows.Forms;
namespace ExceptionTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                int a = 10;
                int b = 0;
                Divide(a, b);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        public static void Divide(int a, int b)
        {
            try
            {
                Console.WriteLine(a / b);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message,ex);
            }
        }
    }
}

这是我们想要的,每个需要处理异常的函数都需使用 new Exception(且包含内部异常),每个不需要处理异常的函数做也不需要做

posted @ 2023-01-01 21:36  我也是个傻瓜  阅读(2196)  评论(0编辑  收藏  举报