• C# 异常处理最佳实践,解决代码分析提示CA1031:不要捕捉一般异常类型的解决办法


    异常类型

    异常一般分为系统异常 和 应用异常。系统异常有无法连接数据库,而应用异常是业务逻辑异常,比如授权失败。

    在 C# 中异常基于 System.Exception,派生出 System.SystemException 和 System.ApplicationException。微软最初设计为 CLR 抛出的异常都继承自 System.SystemException,应用程序抛出的异常应当继承自 System.ApplicationException。但 .NET 框架类库(FCL) 没能很好地遵循这个原则。因此,目前存在的 System.SystemException 和 System.ApplicationException 主要用于兼容。

    1. 在实际业务中,不应该使用 System.SystemException 和 System.ApplicationException
    2. 不要在非顶层中捕获 System.Exception,除非你会在捕获后重新抛出
    3. 在对象不正确的时候,可使用 System.InvalidOperationException 和 System.ArgumentException 和其派生异常。例如给只读对象赋值
    4. 业务异常应该定义一个基于 System.Exception 的自定义异常,并基于自定义的异常再派生具体的异常。例如业务异常为 BusinessException:System.Exception,转账业务异常为 TransferFundsException:BusinessException
    5. 需要给异常填写异常描述
    6. 不要自己抛出 System.StackOverflowException 这类异常
    7. 并不是所有情况都需要使用 try catch 语句,可使用 if 提前判断是否抛出异常,以提高性能

    使用 throw 和 throw ex 的区别

    在 C# 中推荐使用 throw,原因是如果直接使用 throw ex 会清除原始的异常,将 ex 作为新的异常源,从而找不到真正的异常源。

    建议只在最外层做捕获。

    // 错误的用法
    try
    {
    }
    catch(Exception ex)
    {
        throw ex;
    }
    
    // 正确的用法
    try
    {
    }
    catch
    {
      throw;
    }
    
    // 正确的用法
    try
    {
    }
    catch(Exception ex)
    {
      throw new Exception("message", ex);
    }
    
    // 正确的用法
    throw new AppException("message");

    CA1031:不要捕捉一般异常类型

    原因

    一般异常(如 System.Exception 或 System.SystemException)在 catch 语句中捕获,或者使用 catch() 等常规 catch 子句。

    规则说明

    不应捕捉一般异常。

    如何解决冲突

    若要修复与此规则的冲突,请捕获更具体的异常,或者再次引发一般异常作为 catch 块中的最后一条语句。

    何时禁止显示警告

    不禁止显示此规则发出的警告。 捕获一般异常类型可以隐藏库用户的运行时问题,并且可能会使调试变得更加困难。

    示例

    下面的示例显示一个与此规则冲突的类型和一个正确实现 catch 块的类型。

    using System;
    using System.IO;
    
    namespace DesignLibrary
    {
        // Creates two violations of the rule.
        public class GenericExceptionsCaught
        {
            FileStream inStream;
            FileStream outStream;
    
            public GenericExceptionsCaught(string inFile, string outFile)
            {
                try
                {
                    inStream = File.Open(inFile, FileMode.Open);
                }
                catch(SystemException e)
                {
                    Console.WriteLine("Unable to open {0}.", inFile);
                }
    
                try
                {
                    outStream = File.Open(outFile, FileMode.Open);
                }
                catch
                {
                    Console.WriteLine("Unable to open {0}.", outFile);
                }
            }
        }
    
        public class GenericExceptionsCaughtFixed
        {
            FileStream inStream;
            FileStream outStream;
    
            public GenericExceptionsCaughtFixed(string inFile, string outFile)
            {
                try
                {
                    inStream = File.Open(inFile, FileMode.Open);
                }
    
                // Fix the first violation by catching a specific exception.
                catch(FileNotFoundException e)
                {
                    Console.WriteLine("Unable to open {0}.", inFile);
                }
    
                try
                {
                    outStream = File.Open(outFile, FileMode.Open);
                }
    
                // Fix the second violation by re-throwing the generic 
                // exception at the end of the catch block.
                catch
                {
                    Console.WriteLine("Unable to open {0}.", outFile);
                    throw;  //手动高亮
                }
            }
        }
    }
  • 相关阅读:
    【转载】COM 组件设计与应用(十一)—— IDispatch 及双接口的调用
    【转载】COM 组件设计与应用(十)——IDispatch 接口 for VC.NET
    网易云课堂_Linux操作系统入门(嵌入式开发零基础Ⅰ)_章节3:Linux 命令(下)
    网易云课堂_Linux操作系统入门(嵌入式开发零基础Ⅰ)_章节2:Linux 命令(上)
    网易云课堂_艾叔:零基础一站式C语言|C程序设计精讲_章节12:指针
    网易云课堂_艾叔:零基础一站式C语言|C程序设计精讲_章节8:输入与输出
    网易云课堂_艾叔:零基础一站式C语言|C程序设计精讲_章节5整型
    Vim应用
    gcc编译命令
    虚拟机使用PuTTY、SSH Secure Shell Client前的配置
  • 原文地址:https://www.cnblogs.com/jopny/p/11849372.html
Copyright © 2020-2023  润新知