zoukankan      html  css  js  c++  java
  • Try-Catch无法正确定位异常位置,我推荐2个有效技巧

    宇宙第一开发IDE Visual Studio的调试功能非常强大,平常工作debug帮助我们解决不少问题。今天分享两个异常捕获的技巧,希望能够帮助解决一些问题。
    以下两种情况,我相信大家都会遇到过。

    • 1.没有使用Try-Catch语句,当异常发生的时候,能够自动跳转到异常发生的地方,在使用Try-Catch捕获异常的时候,直接跳转到Catch语句的位置,并不会自动定位到异常代码的位置。
    • 2.使用Try-Catch的时候,多层方法调用时,并不能直接查看到异常代码的位置。

    技巧1:自动定位到异常代码位置

    针对问题1,我们最想要的结果是,哪里有代码出现错误了,就直接定位到哪儿,异常出在哪行代码上,我一眼就能看得出,这样就能更快地处理问题了。
    对于问题1,所出现的这种情况,简单复现一下一个空引用的异常

    namespace ExceptionSample
    {
        class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    Random random = null;
                    Console.WriteLine(random.Next());
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                Console.ReadLine();
            }
         }
    }     
    

    上面的异常代码NullReferrenceException,Debug模式下,会跳转到catch语句这里。你可能觉得这挺简单的......可实际实际工作中,你的一个方法中仅仅只这一个对象吗?
    在这里插入图片描述
    在实际工作中可能不止random一个对象,代码复杂,对象够多,几十个也有,我们就很难定位到异常出错的代码了。StackTrace可以定位到那个函数调用错了,并不能定位到哪一行代码出错了。
    为了解决这个行为可以通过在Visual Studio中菜单栏中的调试》窗口》异常设置中去配置。如下图所示:
    在这里插入图片描述
    勾选上Common Language Runtime Exceptions下列的异常单选框。有点多,以前的设置有些变化。
    现在我们再看之前的代码,使用Try-Catch语句捕获异常的时候,就会直接定位到异常代码的位置了,如下图示:

           static void Main(string[] args)
            {
                try
                {
                    Random random = null;
                    Random random1 = new Random();
                    Random random2 = new Random();
                    Random random3 = new Random();
                    Console.WriteLine(random1.Next());
                    Console.WriteLine(random2.Next());
                    Console.WriteLine(random3.Next());
                    Console.WriteLine(random.Next());
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                Console.ReadLine();
            }
    

    在这里插入图片描述

    技巧2:正常的throw 姿势

    还是之前的一个方法,我已经将异常设置回复默认了。

            static void Main(string[] args)
            {
                try
                {
                    Random random = null;
                    Console.WriteLine(random.Next());
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.Write(ex);
                    throw ex;
                }
            }
    

    我们再输出中可以看到(ps:项目名称用的之前的,不介意哈)
    在这里插入图片描述
    错误的代码在16行。可实际工作中的情况并不是这样简单,基本上是A方法调用B方法,B方法调用C方法,代码如下所示:
    在Main方法中调用ThrowNullReferrence(),方法ThrowNullReferrence中调用SetNullReferrence()。代码变复杂后,一层嵌套一层。这个时候能正确显示出代码异常的位置吗?

            static void Main(string[] args)
            {
                try
                {
                    ThrowNullReferrence();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.Write(ex);
                    throw ex;
                }
            }
            public  static void ThrowNullReferrence()
            {
                try
                {
                    SetNullReferrence();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.Write(ex);
                    throw ex;
                }
            }
            public static void SetNullReferrence()
            {
                try {
                    Random random = null;
                    Console.WriteLine(random.Next());
                }
                catch(Exception ex)
                {
                    System.Diagnostics.Debug.Write(ex);
                    throw ex;
                }
            }
    

    我们可以通过下图看到:
    在这里插入图片描述
    System.NullReferenceException: 未将对象引用设置到对象的实例。
    在 ExceptionSample.Program.SetNullReferrence() 位置 D:Learn延迟加载LinqLayzLoadLinqLayzLoadProgram.cs:行号 39System.NullReferenceException: 未将对象引用设置到对象的实例。
    在 ExceptionSample.Program.SetNullReferrence() 位置 D:Learn延迟加载LinqLayzLoadLinqLayzLoadProgram.cs:行号 44
    在 ExceptionSample.Program.ThrowNullReferrence() 位置 D:Learn延迟加载LinqLayzLoadLinqLayzLoadProgram.cs:行号 27System.NullReferenceException: 未将对象引用设置到对象的实例。
    在 ExceptionSample.Program.ThrowNullReferrence() 位置 D:Learn延迟加载LinqLayzLoadLinqLayzLoadProgram.cs:行号 32
    在 ExceptionSample.Program.Main(String[] args) 位置 D:Learn延迟加载LinqLayzLoadLinqLayzLoadProgram.cs:行号 15

    错误代码的位置在39行,以上出现异常的地方都是throw的位置。
    原因呢?
    catch捕获完后,如果要向上抛出,应该重新实例化一个新的异常对象,再向上抛出,这个最外层方法catch到的才是完整的异常,当然也包括完整的堆栈信息,这样才能定位到异常代码的位置。
    要使用 throw new Exception
    改造后的例子如图,精准定位到
    39行的空引用异常
    Console.WriteLine(random.Next());
    在这里插入图片描述

    结语

    分享之前看到的一个老程序员的经验之谈:“多coding,少debug”

  • 相关阅读:
    .NET Core开发的iNeuOS物联网平台部署在Ubuntu操作系统,无缝跨平台。助力《2019 中国.NET 开发者峰会》。
    iNeuOS 物联网云操作系统2.0发布,集成设备容器、视图建模、机器学习三大模块
    .Net for Spark 实现 WordCount 应用及调试入坑详解
    实际项目中,看 ECharts 和 HighCharts 渲染性能对比,表面看衣装,本质看内功!!!
    iNeuOS云操作系统,.NET Core全系打造
    《ServerSuperIO Designer IDE使用教程》- 7.增加机器学习算法,通讯采集数据与算法相结合。发布:4.2.5 版本
    《ServerSuperIO Designer IDE使用教程》- 6.增加与阿里云物联网(IOT)对接服务,实现数据交互。发布:v4.2.4 版本
    《ServerSuperIO Designer IDE使用教程》- 5.树形结构管理设备驱动,小版本更新。发布:v4.2.3.1版本
    《ServerSuperIO Designer IDE使用教程》-4.增加台达PLC驱动及使用教程,从0到1的改变。发布:v4.2.3版本
    物联网框架ServerSuperIO.Core(.netcore)跨平台,一套设备驱动通吃嵌入式、上位机、云服务
  • 原文地址:https://www.cnblogs.com/zhangmumu/p/12007159.html
Copyright © 2011-2022 走看看