C#笔记9:异常

简介:

C#笔记9:异常

本章概要:

1:为什么需要异常 
2:finally 
3:什么时候需要捕获异常 
4:什么时候需要抛出异常 
5:异常处理中的错误做法 
6:为什么需要自定义异常 
7:自定义异常的设计要素 
8:什么时候不需要自定义异常  

 

1:为什么需要异常

 

      利用异常处理,我们可以将资源清理代码放在一个固定的位置,并且确保它们得到执行。
     利用异常处理,我们可以将异常处理的代码放在一个集中的位置。
     异常处理的强制性,和前一个好处密切相关的可能是异常处理所带来的最大好处。
     利用异常处理,我们可以很容易定位和修复代码中的bug。   

 

2:finally

 

     即使发生异常也会执行 finally 块中的代码。使用 finally 块释放资源,例如,关闭在 try 块中打开的任何流或文件。 
    在 finally 块中关闭数据库连接是另一个不错的选择。 因为有时候数据库服务器允许的连接数是有限的,所以应尽快关闭数据库连接。 在由于引发了异常而无法关闭连接的情况下,使用 finally 块也是比等待垃圾回收更好的一种选择。  

 

3:什么时候需要捕获异常

 

      当下列条件为真时,应该捕捉异常: 
     a、对引发异常的原因有具体的了解,并可实现特定的恢复,例如,捕捉 FileNotFoundException 对象并提示用户输入新的文件名。
     b、可以新建一个更具体的异常并引发该异常。例如:

int GetInt(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch(System.IndexOutOfRangeException e)
    {
        throw new System.ArgumentOutOfRangeException(
            "Parameter index is out of range.");
    }
}    

 

     c、部分处理异常。例如,可以使用 catch 块向错误日志中添加项,但随后重新引发该异常,以便对该异常进行后续处理。例如:

try
{
    // try to access a resource
}
catch (System.UnauthorizedAccessException e)
{
    LogError(e);  // call a custom error logging procedure
    throw e;      // re-throw the error
}

 

4:什么时候需要抛出异常

     a、方法无法完成其中定义的功能。 
         例如,如果方法的参数具有无效值:

static void CopyObject(SampleClass original)
{
    if (original == null)
    {
        throw new System.ArgumentException("Parameter cannot be null", "original");
    }

}

 

 

     b、根据对象的状态,对某个对象进行不适当的调用。
     一个示例可能尝试对只读文件执行写操作。在对象状态不允许某项操作的情况下,引发 InvalidOperationException 的一个实例或基于此类的派生类的对象。以下为引发 InvalidOperationException 对象的方法的示例:

class ProgramLog
{
    System.IO.FileStream logFile = null;
    void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {}

    void WriteLog()
    {
        if (!this.logFile.CanWrite)
        {
            throw new System.InvalidOperationException("Logfile cannot be read-only");
        }
        // Else write data to the log and return.
    }
}  

 

     c、方法的参数导致了异常。
     在此情况下,应捕获原始异常并创建一个 ArgumentException 实例。原始异常应作为 InnerException 参数传递给ArgumentException 的构造函数:

static int GetValueFromArray(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch (System.IndexOutOfRangeException ex)
    {
        System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex);
        throw argEx;
    }
}
 

 

5:异常处理中的错误做法

 

      不要通过在框架代码中捕捉非特定异常(如 System.Exception、System.SystemException 等)来处理错误。 
     如果捕捉异常是为了再次引发或传输给其他线程,则可以捕捉这些异常。 
     不要显式引发 System.StackOverflowException。此异常仅应由公共语言运行时 (CLR) 显式引发。
     不要捕捉 System.StackOverflowException。以编程方式处理堆栈溢出极为困难。应允许此异常终止进程并使用调试确定问题的根源。 
     不要显式引发 System.OutOfMemoryException。此异常仅应由 CLR 基础结构引发。
     不要显式引发 System.Runtime.InteropServices.COMException 或 System.Runtime.InteropServices.SEHException。这些异常仅应由 CLR 基础结构引发。 
     不要显式捕捉 System.Runtime.InteropServices.SEHException。 
     不要显式引发 System.ExecutionEngineException。  

 

6:为什么需要自定义异常

 

      如果要对某类程序出错信息作出特殊处理了,那就自定义异常。
     方便调试,通过抛出一个我们自己定义的异常类型实例,我们可以使捕获代码精确地知道所发生的事情,并以合适的方式进行恢复。 
     逻辑包装,自定义异常可包装多个其它异常,然后抛出一个业务异常。 
     方便调用者编码,在编写自己的类库或者业务层代码的时候,自定义异常可以让调用方更方便处理业务异常逻辑。如保存数据失败,可以分成两个异常“数据库连接失败。”、“网络异常。” 
     引入新异常类,使程序员能够根据异常类在代码中采取不同的操作。

 

 

7:自定义异常的设计要素

     异常类名称一定要以后缀 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.
   }
}

 

8:什么时候不需要自定义异常

     考虑引发 System 命名空间中的现有异常,而不是创建自定义异常类型。
     如果错误状态可以通过不同于现有任何其他异常的方法以编程方式进行处理,则要创建并引发自定义异常。否则,引发一个现有异常。
     不要只是为了您所在的团队获得异常而创建和引发新异常。

 

练习:

1.You are working on a debug build of an application.    You need to find the line of code that caused an exception to be thrown. Which property of the Exception class should you use to achieve this goal?    
A. Data 
B. Message 
C. StackTrace  
D. Source

Answer: C

 

2.You write the following custom exception class named CustomException.      
 public class CustomException:ApplicationException{

    public static int COR_E_ARGUMENT=unchecked((int)0x80070075);

    public CustomException(string msg):base(msg) {HResult=COR_E_ARGUMENT;}

 }
You need to write a code segment that will use the CustomException class to immediately return control to the COM caller. You also need to ensure that the caller has access to the error code. Which code segment should you  use? 

A. return Marshal.GetExceptionForHR(CustomException.COR_E_ARGUMENT); 
B. return CustomException.COR_E_ARGUMENT; 
C. Marshal.ThrowExceptionForHR(CustomException.COR_E_ARGUMENT);

D. throw new CustomException("Argument is out of bounds"); 
Answer: D

本文转自最课程陆敏技博客园博客,原文链接:http://www.cnblogs.com/luminji/archive/2010/10/20/1823536.html,如需转载请自行联系原作者
相关文章
|
7月前
|
C# Python
C# 笔记1 - 操作目录
C# 笔记1 - 操作目录
59 0
|
2月前
|
算法 安全 测试技术
C#——刘铁猛笔记
C#——刘铁猛笔记
51 0
|
4月前
|
安全 测试技术 数据库连接
如何避免 C# 中的异常
【8月更文挑战第27天】
57 2
|
4月前
|
安全 C# 开发者
【C# 多线程编程陷阱揭秘】:小心!那些让你的程序瞬间崩溃的多线程数据同步异常问题,看完这篇你就能轻松应对!
【8月更文挑战第18天】多线程编程对现代软件开发至关重要,特别是在追求高性能和响应性方面。然而,它也带来了数据同步异常等挑战。本文通过一个简单的计数器示例展示了当多个线程无序地访问共享资源时可能出现的问题,并介绍了如何使用 `lock` 语句来确保线程安全。此外,还提到了其他同步工具如 `Monitor` 和 `Semaphore`,帮助开发者实现更高效的数据同步策略,以达到既保证数据一致性又维持良好性能的目标。
57 0
|
6月前
|
关系型数据库 C# 数据库
技术笔记:MSCL超级工具类(C#),开发人员必备,开发利器
技术笔记:MSCL超级工具类(C#),开发人员必备,开发利器
57 3
|
6月前
|
开发框架 .NET 程序员
掌握C#语言的精髓:基础知识与实用技能详解(数据类型与变量+ 条件与循环+函数与模块+LINQ+异常+OOP)
掌握C#语言的精髓:基础知识与实用技能详解(数据类型与变量+ 条件与循环+函数与模块+LINQ+异常+OOP)
34 0
|
6月前
|
Java BI C#
技术笔记:SM4加密算法实现Java和C#相互加密解密
技术笔记:SM4加密算法实现Java和C#相互加密解密
105 0
|
7月前
|
开发框架 安全 .NET
C# .NET面试系列三:集合、异常、泛型、LINQ、委托、EF!
<h2>集合、异常、泛型、LINQ、委托、EF! #### 1. IList 接口与 List 的区别是什么? IList 接口和 List 类是C#中集合的两个相关但不同的概念。下面是它们的主要区别: <b>IList 接口</b> IList 接口是C#中定义的一个泛型接口,位于 System.Collections 命名空间。它派生自 ICollection 接口,定义了一个可以通过索引访问的有序集合。 ```c# IList 接口包含一系列索引化的属性和方法,允许按索引访问、插入、移除元素等。 由于是接口,它只定义了成员的契约,而不提供具体的实现。类似于 IEnumera
359 2
|
7月前
|
C# Python
C# 笔记3 - 重载一系列像python那样的print()方法
C# 笔记3 - 重载一系列像python那样的print()方法
52 1