译《异常最佳实践》

原文: 《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这样的全局异常类。

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

译《异常最佳实践》的相关文章

译:SOS_SCHEDULER_YIELD类型等待在虚拟机环境中的增多

原文出处:Increased SOS_SCHEDULER_YIELD waits on virtual machines 注: 原文的用词是Increased,想译作增强(增长),或者加强,这么译起来是褒义词,而原文要表达的Increased并没有褒义的含义,最起码是一个中性的含义,想来想起用一个“滋长”偏编译的含义还是比较合适的,感觉还是有点过于贬义了,还是用最通俗的增多吧.个人英语水平有限,另外就是对于文中提到的“rdtsc周期”也不是非常清楚,翻译的也不是很清楚,权当是自娱自乐.总是原文的

《100种过度医疗大公开》:转译自日文版,日文版依据的是美国的“Choosing Wisely”项目。三星推荐

本书转译自日文,日文版则是在美国的“Choosing Wisely”项目中选择了100个相对常见的过度医疗项目做解说.Choosing Wisely项目,是由美国多个专业医学组织发起的列出过度医疗项目的活动. 日文作者是兽医专业的新闻记者,中文译者不是医学专业人员,个别专业词语翻译有误,“随机对照试验”翻译成“随机比较试验”了,有些句子翻译的也比较别扭.基于以上两点,这本书的权威性可信度我认为都不算太高,只能给三星.感兴趣的话还是应该直接上网看英文原版. 以下是书中部分信息的摘抄: 1:以美国内

博译有道——关于外文书籍的翻译

有人说,中国古代曾经被人津津乐道的诸如木流牛马之类的工匠发明和创造之所以没有被后人所重现,是因为创作者只知其术,不懂传道.在门户之见成风,传道授艺大多通过手把手教.口口相传的古代,可想而知像<本草纲目>这样的著作的重要性.同样在今天,无论是原创,还是转载,通过互联网广泛传播碎片化知识的同时,作为系统性的.汇总性的书籍显得颇为难能可贵,即便是将一本国外早已出版的书籍引入到国内出版. 经过长达六个月的付出和守候,由IDF实验室成员翻译.机械工业出版社出版的<Hacking with Kali

[email&#160;protected]一个高效的配置管理工具--Ansible configure management--翻译(六)

无书面许可请勿转载 高级playbook Finding files with variables All modules can take variables as part of their arguments by dereferencing them with {{ and }} . You can use this to load a particular file based on a variable. For example, you might want to select a

[译]JavaScript中,{}+{}等于多少?

[译]JavaScript中,{}+{}等于多少? 原文:http://www.2ality.com/2012/01/object-plus-object.html 最近,Gary Bernhardt在一个简短的演讲视频“Wat”中指出了一个有趣的JavaScript怪癖:在把对象和数组混合相加时,会得到一些你意想不到的结果.本篇文章会依次讲解这些计算结果是如何得出的. 在JavaScript中,加法的规则其实很简单,只有两种情况:你只能把数字和数字相加,或者字符串和字符串相加,所有其他类型的值

[译]WordPress 4.3 将会用node.js重写

一个核心的wordpress开发者Ryan Boren表示,wordpress4.3 cms系统将会有一个重大的变革,那就是用node.js重写,同时完全兼容之前的版本. WordPress 和 Node.js 开发者以及项目本身已经关注node.js很久了,当然,这早就不是什么秘密了,node.js允许你用javascript写服务端代码. 我们首次使用node.js是在3.7版本中,同时也把Grunt工具加入了我们的开发周期中.自那以后,越来越多的核心版本开始使用javascript,NB的

storm源码之storm代码结构【译】【转】

[原]storm源码之storm代码结构[译] 说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于Storm进行源码级学习和研究的朋友有所帮助. Storm的源码共分为三个不同的层次. 首先,Storm在设计之初就考虑到了兼容多语言开发.Nimbus是一个thrift服务,topologies被定义为Thrift结构体.Thrift的运用使得Storm可以被任意开发语言使用. 其次,Stor

AFNnetworking快速教程,官方入门教程译

AFNnetworking快速教程,官方入门教程译 分类: IOS2013-12-15 20:29 12489人阅读 评论(5) 收藏 举报 afnetworkingjsonios入门教程快速教程 AFNetworking官网入门教程简单翻译,学习 AFNetworking 是一个能够快速使用的ios和mac os x下的网络框架,它是构建在Foundation URL Loading System之上的,封装了网络的抽象层,可以方便的使用,AFNetworking是一个模块化架构,拥有丰富ap

[译]最长回文子串(Longest Palindromic Substring) Part II

[译+改]最长回文子串(Longest Palindromic Substring) Part II 问题:给定字符串S,求S中的最长回文子串. 在上一篇,我们给出了4种算法,其中包括一个O(N2)时间O(1)空间的算法(中心检测法),已经很不错了.本篇将讨论一个O(N)时间O(N)空间的算法,即著名的Manacher算法,并详细说明其时间复杂度为何是O(N). 提示 +BIT祝威+悄悄在此留下版了个权的信息说: 先想想有什么办法能改进中心检测法. 考虑一下最坏的情况.★ 最坏的情况就是各个回文

[译]用AngularJS构建大型ASP.NET单页应用(一)

原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single 渣译,各位看官请勿喷 引言: ... 单页面应用程序(SPA),被定义为在一个独立的页面上??提供类似于桌面应用程序级用户体验为目标的网站.在SPA, 基本上所有的代码 - 例如 HTML,JavaScript和CSS - 都是在响应用户操作时动态加载的.页面没有在任何时候被重新刷新,也没有跳转到另一