Try-Catch无法正确定位异常位置,我推荐2个有效技巧

简介: 这个n到底是多少年?宇宙第一开发IDE Visual Studio的调试功能非常强大,平常工作debug帮助我们解决不少问题。今天分享两个异常捕获的技巧,希望能够帮助解决一些问题。

这个n到底是多少年?宇宙第一开发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语句这里。你可能觉得这挺简单的…可实际实际工作中,你的一个方法中仅仅只这一个对象吗?
csdn1
在实际工作中可能不止random一个对象,代码复杂,对象够多,几十个也有,我们就很难定位到异常出错的代码了。StackTrace可以定位到那个函数调用错了,并不能定位到哪一行代码出错了。

为了解决这个行为可以通过在Visual Studio中菜单栏中的调试》窗口》异常设置中去配置。如下图所示:
csdn2
勾选上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();
        }

csdn4
技巧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:项目名称用的之前的,不介意哈)
csdn5
错误的代码在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;
            }
        }

我们可以通过下图看到:
csdn6
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());
csdn7
结语
分享之前看到的一个老程序员的经验之谈:“多coding,少debug”,
回到标题为什么说"使用Vistual Studio n年",这个n到底指的是多少年。我的意思是可能有些东西,即使使用多年,可能不知道这两个技巧。

文章来源:https://blog.csdn.net/kebi007/article/details/103439933
更多技术内容:https://www.roncoo.com

相关文章
|
10月前
|
存储 分布式计算 大数据
大数据 优化数据读取
【11月更文挑战第4天】
258 2
|
前端开发 Java 应用服务中间件
如何获取HTTP请求时间与响应时间【附源码】
如何获取HTTP请求时间与响应时间【附源码】
933 0
|
机器学习/深度学习 存储 自然语言处理
SeACo-Paraformer
【6月更文挑战第14天】
596 6
|
11月前
|
存储 JavaScript 数据库
ToB项目身份认证AD集成(一):基于目录的用户管理、LDAP和Active Directory简述
本文介绍了基于目录的用户管理及其在企业中的应用,重点解析了LDAP协议和Active Directory服务的概念、关系及差异。通过具体的账号密码认证时序图,展示了利用LDAP协议与AD域进行用户认证的过程。总结了目录服务在现代网络环境中的重要性,并预告了后续的深入文章。
427 2
|
JavaScript
Vue3滑动输入条(Slider)
这是一个可高度定制的滑动输入条组件,支持多种配置选项,如宽度、最小值、最大值、是否禁用、双滑块模式等。主要功能包括点击滑动条快速定位并获取数值、拖动滑块调整数值、键盘操作调整数值以及自定义Tooltip显示格式。组件通过监听DOM尺寸变化来动态调整布局,并利用requestAnimationFrame优化动画效果,提供了丰富的交互体验。在线预览和详细代码示例可见[这里](https://themusecatcher.github.io/vue-amazing-ui/guide/components/slider.html)。
348 4
Vue3滑动输入条(Slider)
|
移动开发 前端开发 JavaScript
如何向后兼容性
如何向后兼容性
|
Kubernetes Cloud Native 应用服务中间件
Kubernetes 自动伸缩策略:优化资源利用率
【8月更文第29天】在现代云原生环境中,应用的流量往往具有不可预测性。为了应对这种变化,Kubernetes 提供了多种自动伸缩机制来动态调整应用实例的数量和每个实例分配的资源。本文将深入探讨两种主要的自动伸缩工具:水平 Pod 自动伸缩器 (HPA) 和垂直 Pod 伸缩器 (VPA),并提供实际的应用示例。
335 1
|
存储 关系型数据库 MySQL
mysql optimizer_switch : 查询优化器优化策略深入解析
mysql optimizer_switch : 查询优化器优化策略深入解析
|
关系型数据库 MySQL 数据库
MySQL 和 PostgreSQL,我到底选择哪个?
MySQL 和 PostgreSQL,我到底选择哪个?
15179 0
|
SQL 大数据 数据挖掘
深入解析力扣178题:分数排名(DENSE_RANK详解及模拟面试问答)
深入解析力扣178题:分数排名(DENSE_RANK详解及模拟面试问答)

热门文章

最新文章