• 巧用Using跳过异常捕获


    前言

        这里主要说一个使用using躲过异常的小技巧。

        我原来就遇到过类似的问题好几次了,也没想到办法,直接有一天,调试得实在受不了了,才认真想了以下的解决方案。


    问题

        原来的代码是这样的:

    public abstract class Command : RoutedUICommand
    {
        private bool _isExecuting = false;
    
        public void Execute(CommandContext commandContext)
        {
            this._isExecuting = true;
            try
            {
                OnExecute(commandContext);
            }
            catch
            {
                throw;
            }
            finally
            {
                this._isExecuting = false;
            }
        }
    
        protected abstract void OnExecute(CommandContext commandContext);
    }

        这是一个抽象的命令类,这里只贴出了这个问题的主要的逻辑:需要在OnExecute方法执行之前设置_isExecuting的值为true,然后执行OnExecute方法,然后不管是否出现异常,都在执行完毕后,设置为false。子类实现这个类实现OnExecute方法来编写自己真正的执行代码。这时比较麻烦的一个问题是:在代码编写阶段,当子类的OnExecute方法内部出现异常时,Visual Studio都会直接把错误给定在这个类上,如下:

    子类:

    private class ConcreteCommand : Command
    {
        protected override void OnExecute(CommandContext commandContext)
        {
            int i = 0;
            int j = 100 / i;
            //.......
        }
    }

    出现异常:

    image

        调试的过程中,无法直接定位到子类,当代码很多时,找实现这个基类的子类是很烦人的事。而且找到了它以后,打上断点,还得重新运行一遍来运行同样的bug路径。时间就是这样浪费的,调试得很崩溃……


    解决

        需要重构了基类的代码,但是由于Execute方法的设置_isExecuting字段的逻辑不能改变,所以并不简单。灵光一闪,有了以下的实现:

    public abstract class Command
    {
        public void Execute(CommandContext commandContext)
        {
            this._isExecuting = true;
            using (this.__isExecuting)
            {
                OnExecute(commandContext);
            }
        }
        protected abstract void OnExecute(CommandContext commandContext);
    
        private bool _isExecuting
        {
            get
            {
                return this.__isExecuting.Value;
            }
            set
            {
                this.__isExecuting.Value = value;
            }
        }
        private IsExecutingWrapper __isExecuting = new IsExecutingWrapper();
    
        /// <summary>
        /// 原来的模式增加了调试的困难度。
        /// 添加这个方法方便调试。
        /// </summary>
        private class IsExecutingWrapper : IDisposable
        {
            private bool _value;
            public bool Value
            {
                get
                {
                    return this._value;
                }
                set
                {
                    this._value = value;
                }
            }
    
            #region IDisposable Members
    
            public void Dispose()
            {
                this._value = false;
            }
    
            #endregion
        }
    }
    

        成功解决:

    image


    后话

        因为我不只一次遇到过这个问题,所以我猜测肯定还会有朋友会遇到同样的问题。所以就把这个小问题冒昧的发在了首页。希望和大家分享。另外,如果你有更好的方法,可以用力的拍我。 :)

  • 相关阅读:
    Python学习笔记——基础篇【第二周】——解释器、字符串、列表、字典、主文件判断、对象
    HashMap、HashTable、ConcurrentHashMap、TreeMap、LinkedHashMap、WeakHashMap区别
    IntelliJ IDEA 控制台中文乱码解决方案
    Java 使用 Redis
    redis.conf 配置项说明
    虚拟机性能监控与故障处理工具
    图解Git
    常用git命令
    设计模式的类型
    使用mybatis插件自动生成代码以及问题处理
  • 原文地址:https://www.cnblogs.com/zgynhqf/p/1626658.html
Copyright © 2020-2023  润新知