译《异常最佳实践》

badlands badlands     2022-08-07     740

关键词:

原文: 《Best Practices for Excetpions》

链接:https://msdn.microsoft.com/en-us/library/seyhszts(v=vs.110).aspx

译文:

设计优秀的应用程序能够处理运行过程中出现的异常和错误以避免应用程序崩溃。这篇文章描述了关于处理与创建异常的最佳实践。

处理异常

  • 合适地使用异常处理代码(try/catch 块)。(因为)同样可以通过编程检查经常可能出现异常的条件(情况)而不使用异常处理。
    if (conn.State != ConnectionState.Closed)
    {
        conn.Close();
    }

    如果上面的代码使用异常处理模型,则如下面的例子所示。使用try/catch 块来包裹连接检查,如果连接没有关闭成功,则抛出异常。

    try
    {
        conn.Close();
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.GetType().FullName);
        Console.WriteLine(ex.Message);
    }

    是在编程时使用条件检查还是使用异常处理,这取决于你的预期判断——非预期情况是否经常出现。

    • 使用【异常】处理并不经常发生的事件,也就是说使用【异常】处理那些一旦出现就被认为是错误的情况,比如遇到非预期的文件结尾(你认为文件还没有读完,但但得到了文件结尾符或者没有更多的可读内容)。 当你使用异常处理时,比使用一般的条件判断所写的代码要少。
    • 使用编程方式检查那些依惯例会发生的时间、可以被认为是执行的一部分的情况。如果使用编程检查错误,当错误发生时,则需要执行更多的代码。
  • 使用try/catch块包裹执行代码有潜在的产生异常的可能,如果有需要,最好使用finally块来释放资源。在这种模式下,try语句块产生异常,catch块处理异常,finally语句块在不管有没有异常发生的情况下释放已经分配的资源。
  • 在catch块中,处理异常的顺序是从最具体的异常到抽象的异常。这种技巧在异常被传递到更抽象的异常之前被处理掉。

创建和抛出异常

下节内容包含了创建自己的异常、以及这些异常该在合适被抛出的指南。如果向得到更加详细的参考,可以查看《异常设计准则》

  • 设计的类在一般情况执行下应该永远不要抛出异常。举个例子,FileStream类已经提供了帮助检查文件是否到达结尾的判断方法。这能够帮你避免越过文件结尾还继续读取文件的异常。下面这个例子展示了如何一直读取文件结尾。
    class FileRead
    {
        public void ReadAll(FileStream fileToRead)
        {
            // This if statement is optional
            // as it is very unlikely that
            // the stream would ever be null.
            if (fileToRead == null)
            {
                throw new System.ArgumentNullException();
            }
    
            int b;
    
            // Set the stream position to the beginning of the file.
            fileToRead.Seek(0, SeekOrigin.Begin);
    
            // Read each byte to the end of the file.
            for (int i = 0; i < fileToRead.Length; i++)
            {
                b = fileToRead.ReadByte();
                Console.Write(b.ToString());
                // Or do something else with the byte.
            }
        }
    }
  • 抛出异常以代替返回错误值或者HRESULT的做法。
  • 在错误出现极其平凡的情况下,返回null而不抛出一个异常。极其平常的错误情况可以被认为是一般的控制流。在这种情况下返回null,对应用程序的性能影响最小。
  • 在通常情况下,使用.Net框架预定义的异常类型。只有预定义的类型不够用时才采用一个新的异常类型。
  • 在属性没有被正确设置或者在对象状态不合适的情况下调用某个函数,应该抛出一个InvalidOperationException。
  • 在传递的参数无效的情况下应该抛出ArgumentException或者继承其的异常。
  • 在大部分应用程序中,自定义异常应该继承于Exception类。继承自ApplicationException并不能增加很大的意义。
  • 异常的类名以“Exception”结尾。例如:
    public class MyFileNotFoundException : Exception
    {
    }
  • 在C#和C++中,应该至少提供/使用三个最常见的构造函数来创建自定义类实例:默认构造函数;含有一个消息字符串的构造函数;含有一个消息字符串以及一个内部异常参数的构造函数。如果需要一个例子,可以参见《How to: 创建用户自定义异常》
    • Exception(), 无参数构造函数。
    • Exception(string),接受一个消息字符串。
    • Exception(string, Exception),接受一个消息字符串以及一个内部异常实例。  
  • 当你创建用户自定义异常时,必须确保异常的元数据对远程执行或者跨域执行的代码可见。(比较高级,不展开了)
  • 每个异常都应拥有本地化的描述信息。用户看到的异常信息来自于抛出的异常类的描述字符串,而不是异常类(名)。
  • 使用文法正确的错误消息(串),包含结束标点符号。异常描述的每个句子应该以句号结尾。比如,“日志表已经溢出。”是比较合适的描述语句。
  • 提供更多异常属性以供编程访问。当在一个额外信息对编程场景十分有用的情况下,应该为异常提供额外的属性(额外的更多的描述信息)。 
  • 堆栈轨迹开始于throw,结束语catch语句。决定在哪里抛出异常应该意识到这一情况。
  • 使用异常创建函数。一个类的实现中在不同地方抛出相同的异常时十分普遍的,为了避免冗余的代码,可以使用帮助函数创建并返回异常。以下是一个例子:
    class FileReader
    {
        private string fileName;
    
        public FileReader(string path)
        {
            fileName = path;
        }
    
        public byte[] Read(int bytes)
        {
            byte[] results = FileUtils.ReadFromFile(fileName, bytes);
            if (results == null)
            {
                throw NewFileIOException();
            }
            return results;
        }
    
        FileReaderException NewFileIOException()
        {
            string description = "My NewFileIOException Description";
    
            return new FileReaderException(description);
        }
    }

    同样也可以选择使用异常类的构造函数来创建异常,但这更适合像ArgumentException这样的全局异常类。

  • 在抛出异常时清理中间结果。异常的调用者必须能够确定一个函数抛出异常不会造成副作用。

处理 PyMySql 异常 - 最佳实践

】处理PyMySql异常-最佳实践【英文标题】:HandlingPyMySqlexceptions-BestPractices【发布时间】:2017-05-1116:21:20【问题描述】:我的问题是关于异常最佳实践的。我将就PyMySQL的一个特定案例提出我的问题,但它一般涉及错误处理。我正在... 查看详情

自定义异常消息:最佳实践

】自定义异常消息:最佳实践【英文标题】:CustomExceptionMessages:Bestpractices【发布时间】:2010-10-1207:41:29【问题描述】:想知道在创建异常消息时我应该付出多少努力来强制提供有用的调试信息,还是应该只相信用户提供正确的... 查看详情

Android异常处理最佳实践?

】Android异常处理最佳实践?【英文标题】:Androidexceptionhandlingbestpractice?【发布时间】:2013-05-0919:50:37【问题描述】:如果我的应用崩溃,它会挂起几秒钟,然后Android会告诉我应用崩溃并需要关闭。所以我想用一个通用的方法来... 查看详情

定义自己的异常类的最佳实践?

】定义自己的异常类的最佳实践?【英文标题】:Bestpracticesfordefiningyourownexceptionclasses?【发布时间】:2010-10-1520:44:48【问题描述】:我有一些特殊的异常情况想要抛出和捕获,所以我想定义自己的异常类。这方面的最佳做法是什... 查看详情

捕获和重新抛出异常的最佳实践是啥?

】捕获和重新抛出异常的最佳实践是啥?【英文标题】:Whatarethebestpracticesforcatchingandre-throwingexceptions?捕获和重新抛出异常的最佳实践是什么?【发布时间】:2011-07-2922:18:35【问题描述】:应该直接重新抛出捕获的异常,还是应... 查看详情

捕获和重新抛出 .NET 异常的最佳实践

】捕获和重新抛出.NET异常的最佳实践【英文标题】:Bestpracticesforcatchingandre-throwing.NETexceptions【发布时间】:2010-09-0613:29:45【问题描述】:在捕获异常并重新抛出异常时要考虑哪些最佳做法?我想确保保留Exception对象的InnerExceptio... 查看详情

java异常处理最佳实践及陷阱防范

...工作还是生活中,总会出现各种“错误”,各种突发的“异常”。无论我们做了多少准备,多少测试,这些异常总会在某个时间点出现,如果处理不当或是不及时,往往还会导致其他新的问题出现。所以我们要时刻注意这些陷阱... 查看详情

最佳实践:从属性中抛出异常

】最佳实践:从属性中抛出异常【英文标题】:Bestpractices:throwingexceptionsfromproperties【发布时间】:2010-12-0202:06:55【问题描述】:什么时候从属性getter或setter中抛出异常是合适的?什么时候不合适?为什么?指向有关该主题的外... 查看详情

java处理异常9个最佳实践(代码片段)

...Resource语句使用FinallyJava7的Try-With-Resource语句2.给出准确的异常处理信息3.记录你所指定的异常4.使用描述性消息抛出异常5.最先捕获特定的异常6.不要在catch中使用Throwable7.不要忽略Exceptions8.不要记录和抛出一个异常9.包装异常总结... 查看详情

java异常设计最佳实践(代码片段)

关于异常在讲Java异常实践之前,先理解一下什么是异常。到底什么才算是异常呢?其实异常可以看做在我们编程过程中遇到的一些意外情况,当出现这些意外情况时我们无法继续进程正常的逻辑处理,此时我们就... 查看详情

指示 Func/Proc 抛出异常(如 Java)。最佳实践?

】指示Func/Proc抛出异常(如Java)。最佳实践?【英文标题】:IndicatethataFunc/ProcthrowsanException(likeJava).BestPractice?【发布时间】:2016-04-1506:55:14【问题描述】:我对PLSQL比较陌生,但我有Java方面的背景。因此,我想知道是否有一种... 查看详情

如何使用 try catch 进行异常处理是最佳实践

】如何使用trycatch进行异常处理是最佳实践【英文标题】:Howusingtrycatchforexceptionhandlingisbestpractice【发布时间】:2013-02-0502:06:22【问题描述】:在维护我同事的代码时,即使是自称是高级开发人员的人,我也经常看到以下代码:tr... 查看详情

将唯一违规异常传播到 UI 的最佳实践

】将唯一违规异常传播到UI的最佳实践【英文标题】:BestpracticepropagatingUniqueViolationExceptionstoUI【发布时间】:2012-04-0805:13:55【问题描述】:我们正在开发基于JPA2、Hibernate、Spring3和JSF2在Tomcat7中运行的JavaWeb项目。我们使用Oracle11g... 查看详情

Django - 异常处理最佳实践和发送自定义错误消息 [关闭]

】Django-异常处理最佳实践和发送自定义错误消息[关闭]【英文标题】:Django-exceptionhandlingbestpracticeandsendingcustomizederrormessage[closed]【发布时间】:2016-12-1507:19:17【问题描述】:我开始考虑在我的Django应用程序中进行适当的异常处... 查看详情

Node.js 最佳实践异常处理——在 Async/Await 之后

】Node.js最佳实践异常处理——在Async/Await之后【英文标题】:Node.jsBestPracticeExceptionHandling-AfterAsync/Await【发布时间】:2017-01-3123:25:02【问题描述】:他们已经是关于这个话题的问题了Node.jsBestPracticeExceptionHandling这是旧的,答案非... 查看详情

在线程中处理在 catch 块中抛出的异常的最佳实践。 (。网)

】在线程中处理在catch块中抛出的异常的最佳实践。(。网)【英文标题】:Bestpracticetohandleexception,thatisthrownwithincatchblock,inathread.(.NET)【发布时间】:2010-11-1218:12:08【问题描述】:您对处理线程执行中的异常有何看法?更具体地... 查看详情

Django ajax 错误响应最佳实践

...错误。据我所知,我可以:逐条验证请求数据,逐条防范异常。如果发生了不好的事情,请引发Http404或其他异常以明确宣布发生了错误。或者只需编写没有异常处理的代码并假设它会 查看详情

java编程中关于异常处理的10个最佳实践

异常处理是书写 强健 Java应用的一个重要部分。它是关乎每个应用的一个非功能性需求,是为了优雅的处理任何错误状况,比如资源不可访问,非法输入,空输入等等。Java提供了几个异常处理特性,以try,catch和finally关键... 查看详情