C# 项目异常处理的总结

转载 2012年03月27日 15:09:50

这两天新的项目设计工作快完毕了,我要出一份新项目中的异常书写规则.在msdn上查找了些资料,发现里面很多都是程序员常犯的错误.总结出来,希望对大家有所提高.异常引发准则:不要返回错误代码。

异常是报告框架中的错误的主要手段。通过引发异常来报告执行故障。

如果某一成员无法按预期方式成功执行,则应将这种情况视为一个执行故障并引发一个异常。

如果代码遇到继续执行则不安全的情况,应考虑通过调用 System.Environment.FailFast(System.String)(.NET Framework 2.0 中的一种功能)来终止进程,而不是引发异常。尽可能不对正常控制流使用异常。

除了系统故障及可能导致争用状态的操作之外,框架设计人员还应设计一些 API 以便用户可以编写不引发异常的代码。

例如,可以提供一种在调用成员之前检查前提条件的方法,以便用户可以编写不引发异常的代码。

考虑引发异常的性能影响。

记录公共可调用的成员因成员协定冲突(而不是系统故障)而引发的所有异常,并将这些异常视为协定的一部分。

包含在协定中的异常不应从一个版本更改到下一个版本。

不要包含可以根据某一选项引发或不引发异常的公共成员。

例如,不要定义如下所示的成员:Uri ParseUri(string uriValue, bool throwOnError)不要包含将异常作为返回值或输出参数返回的公共成员。

考虑使用异常生成器方法。

从不同的位置引发同一异常会经常发生。

为了避免代码膨胀,请使用帮助器方法创建异常并初始化其属性。

不要从异常筛选器块中引发异常。当异常筛选器引发异常时,公共语言运行库 (CLR) 将捕获该异常,然后该筛选器返回 false。此行为与筛选器显式执行和返回 false 的行为无法区分,因此很难调试。避免从 finally 块中显式引发异常。

可以接受因调用引发异常的方法而隐式引发的异常。

异常处理准则:不要在框架代码中捕捉非特定异常(如 System.Exception、System.SystemException 等)以至忽略错误。

下面的代码示例演示的异常处理是不正确的。 public class BadExceptionHandlingExample1{ public void DoWork() { // Do some work that might throw exceptions. } public void MethodWithBadHandler() { try { DoWork(); } catch (Exception e) { // Swallow the exception and continue // executing. } }}复制代码避免在应用程序代码中捕捉非特定异常(如 System.Exception、System.SystemException 等)以至忽略错误。某些情况下,可以在应用程序中忽略错误,但这种情况极少。如果捕捉异常是为了传输异常,则不要排除任何特殊异常。下面的代码示例演示对以再次引发为目的特殊异常进行的不正确测试。 public class BadExceptionHandlingExample2{ public void DoWork() { // Do some work that might throw exceptions. } public void MethodWithBadHandler() { try { DoWork(); } catch (Exception e) { if (e is StackOverflowException || e is OutOfMemoryException) throw; // Handle exception and continue // executing. } }}复制代码如果了解特定异常在给定上下文中引发的条件,请考虑捕捉这些异常。不要过多使用 catch。通常应允许异常在调用堆栈中往上传播。使用 try-finally 并避免将 try-catch 用于清理代码。在书写规范的异常代码中,try-finally 比 try-catch 使用得更多。捕捉并再次引发异常时,首选使用空引发。这是保留异常调用堆栈的最佳方式。下面的代码示例演示一个可引发异常的方法。 public void DoWork(Object anObject){ // Do some work that might throw exceptions. if (anObject == null) { throw new ArgumentNullException("anObject", "Specify a non-null argument."); } // Do work with o.}复制代码下面的代码示例演示捕捉一个异常,并在再次引发该异常时对它进行错误的指定。这会使堆栈跟踪指向再次引发作为错误位置,而不是指向 DoWork 方法。 public void MethodWithBadCatch(Object anObject){ try { DoWork(anObject); } catch (ArgumentNullException e) { System.Diagnostics.Debug.Write(e.Message); // This is wrong. throw e; // Should be this: // throw; }}复制代码不要使用无参数 catch 块来处理不符合 CLS 的异常(不是从 System.Exception 派生的异常)。支持不是从 Exception 派生的异常的语言可以处理这些不符合 CLS 的异常。捕捉和引发标准异常类型:Exception 和 SystemException不要引发 System.Exception 或 System.SystemException。不要在框架代码中捕捉 System.Exception 或 System.SystemException,除非打算再次引发。避免捕捉 System.Exception 或 System.SystemException,在顶级异常处理程序中除外。ApplicationException不要引发 System.ApplicationException 或从该异常进行派生。InvalidOperationException如果处于不适当的状态,则引发 System.InvalidOperationException 异常。如果没有向属性集或方法调用提供适当的对象当前状态,则应引发 System.InvalidOperationException。例如,向已打开用于读取的 System.IO.FileStream 写入时,应引发 System.InvalidOperationException 异常。ArgumentException、ArgumentNullException 和 ArgumentOutOfRangeException如果向成员传递了错误的参数,则引发 System.ArgumentException 或其子类型之一。如果适用,首选派生程度最高的异常类型。在引发 System.ArgumentException 或其派生类型之一时,设置 System.ArgumentException.ParamName 属性。此属性存储导致引发异常的参数的名称。注意,使用其中一个构造函数重载可以设置该属性。使用属性 setter 的隐式值参数的名称的值。不要允许公开可调用的 API 显式或隐式引发 System.NullReferenceException、System.AccessViolationException、System.InvalidCastException 或 System.IndexOutOfRangeException。进行参数检查以避免引发这些异常。引发这些异常会公开方法的实现细节,这些细节可能会随时间发生更改。StackOverflowException不要显式引发 System.StackOverflowException。此异常只应由公共语言运行库 (CLR) 显式引发。不要捕捉 System.StackOverflowException。以编程方式处理堆栈溢出极为困难。应允许此异常终止进程并使用调试确定问题的根源。OutOfMemoryException不要显式引发 System.OutOfMemoryException。此异常只应由 CLR 基础结构引发。ComException 和 SEHException不要显式引发 System.Runtime.InteropServices.COMException 或 System.Runtime.InteropServices.SEHException。这些异常只应由 CLR 基础结构引发。不要显式捕捉 System.Runtime.InteropServices.SEHException。ExecutionEngineException不要显式引发 System.ExecutionEngineException。设计自定义异常:避免使用深的异常层次结构。一定要从 System.Exception 或其他常见基本异常之一派生异常。请注意,捕捉和引发标准异常类型中有一条规定,不应从 ApplicationException 派生自定义异常。异常类名称一定要以后缀 Exception 结尾。应使异常可序列化。异常必须可序列化才能跨越应用程序域和远程处理边界正确工作。一定要在所有异常上都提供(至少是这样)下列常见构造函数。请确保参数的名称和类型与使用者相同.代码如下: public class NewException : BaseException, ISerializable{ public NewException() { // Add implementation. } public NewException(string message) { // Add implementation. } public NewException(string message, Exception inner) { // Add implementation. } // This constructor is needed for serialization. protected NewException(SerializationInfo info, StreamingContext context) { // Add implementation. }}复制代码一定要只在要求适合的权限后,才通过 System.Object.ToString 的重写报告安全敏感信息。如果权限要求失败,则返回一个不包括安全敏感信息的字符串。一定要以私有异常状态存储有用的安全敏感信息。请确保只有受信任的代码才能获取该信息。考虑提供异常属性,以便可以以编程方式访问除消息字符串之外与异常相关的额外信息。异常和性能:不要由于担心异常可能会对性能造成不良影响而使用错误代码。对于可能在常见方案中引发异常的成员,可以考虑使用 Tester-Doer 模式来避免与异常相关的性能问题。Doer的代码如下: public class Doer{ // Method that can potential throw exceptions often. public static void ProcessMessage(string message) { if (message == null) { throw new ArgumentNullException("message"); } } // Other methods...}复制代码Tester代码如下: public class Tester{ public static void TesterDoer(ICollection messages) { foreach (string message in messages) { // Test to ensure that the call // won't cause the exception. if (message != null) { Doer.ProcessMessage(message); } } }}复制代码对于可能在常见方案中引发异常的成员,可以考虑使用 TryParse 模式来避免与异常相关的性能问题。代码如下: int i = 0; int j = 0; bool IsPre1 = Int32.TryParse("30",out i); bool IsPre2 = Int32.TryParse("12s",out j); //执行之后i = 30 , j = 0 ; IsPre1 = true, IsPre2 = false;复制代码

C# 项目总结

项目总结 通过这次RFID数据采集程序的设计与开发,从编码能力,编码效率,解决问题的能力,分析问题的思维都受益匪浅都获得了很大提高。为以后的软件开发奠定了良好的基础。不过也发现了自己的不足,正视利弊...
  • szstephenzhou
  • szstephenzhou
  • 2012年09月19日 14:56
  • 1494

c#项目近期阶段学习总结

1、接口     接口A  ,实现接口A的类B 、类C ,操作类D:   一、类B、类C是实现接口的不同实例对象,类B与类C实现接口的方法时不同的,只是方法名相同  二、类D中包含接口A的,在类...
  • u014196922
  • u014196922
  • 2016年10月25日 20:43
  • 141

C# winform 开发总结 -- 【持续更新】

此文章将记录我在C# Winform 开发过程中遇到的问题及相关知识技术点 ,方便自己以后查阅........
  • taoerit
  • taoerit
  • 2017年08月21日 11:55
  • 390

C#异常处理总结

关于异常,从我们一开始写代码的时候就开始伴随着我们,只不过那时还没入门,脑子里并没有产生意识这就是异常。 异常:程序运行期间发生错误, 异常对象: 将程序发生的各种错误封装成对象...
  • kebi007
  • kebi007
  • 2017年10月12日 23:27
  • 3795

电商后台项目总结

1.项目管理 2.dataModel.edmx(实体模型工具) 3.用类库生成BLL 4.项目名称命名规范-->公司名+项目名称+模块名称 5.建库时的要求: a.表中一定要有主键 b.主...
  • wangyihero8
  • wangyihero8
  • 2013年02月13日 10:31
  • 1079

项目全局异常处理

使用HandlerExceptionResolver接口
  • hweixing123
  • hweixing123
  • 2014年10月30日 11:23
  • 325

javaWeb 项目整体异常处理方案

http://www.iteye.com/topic/1073599 在实际的j2ee项目中,系统内部难免会出现一些异常,如果把异常放任不管直接打印到浏览器可能会让用户感觉莫名其妙,也有可能让某些...
  • yanghaijianyumi
  • yanghaijianyumi
  • 2014年03月11日 16:02
  • 1281

C# 多线程异常处理

问题1:子线程中的未处理异常会影响主线程的运行吗? 问题2:如何捕获子线程和主线程中所有的未处理异常? 示例代码: class Program { static v...
  • chthq
  • chthq
  • 2013年11月25日 11:08
  • 1651

C# 消息处理学习总结

C# 收发和处理自定义的WINDOWS消息 http://blog.sina.com.cn/s/blog_45eaa01a01013zbs.html   为了程序启动后自动执行主函数,在F...
  • bcbobo21cn
  • bcbobo21cn
  • 2017年04月08日 09:32
  • 857

贪吃蛇项目总结

以下总结,在此次项目中遇到的问题以及解决方法: 控制台 显示设置: #include //void pf(int x, int y, const char & ch) // X坐标, y坐标, 输出...
  • qq_25235869
  • qq_25235869
  • 2016年04月29日 11:49
  • 1849
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C# 项目异常处理的总结
举报原因:
原因补充:

(最多只允许输入30个字)