C#异常处理

来源:互联网 发布:青岛知豆在哪租的 编辑:程序博客网 时间:2024/05/17 22:40

C#异常处理

参考官方文档异常和异常处理(C# 编程指南)

C# 异常处理时建立在四个关键词之上的:trycatchfinallythrow

  • try:一个 try 块标识了一个将被激活的特定的异常的代码块。后跟一个或多个 catch 块。
  • catch:程序通过异常处理程序捕获异常。catch 关键字表示异常的捕获。
  • finallyfinally 块用于执行给定的语句,不管异常是否被抛出都会执行。例如,如果您打开一个文件,不管是否出现异常文件都要被关闭。
  • throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成。

异常是最终全都派生自 c 的类型。System.Exception类有几个非常有用的属性:

  • StackTrace-当前调用堆栈上的方法的名称,以及为每个方法引发异常的位置(文件名和行号)
  • Message-解释发生异常的原因

自定义异常

自定义异常类要继承自System.Exception, 派生类应至少定义四个构造函数

  • 一个默认构造函数
  • 一个用于设置消息属性的构造函数
  • 一个用于设置 MessageInnerException 属性的构造函数
  • 一个用于序列化异常的构造函数

可参考Part 42 - C# Tutorial - Custom Exceptions

如下:

[Serializable()]public class InvalidDepartmentException : System.Exception{    public InvalidDepartmentException() : base() { }    public InvalidDepartmentException(string message) : base(message) { }    public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }    // A constructor is needed for serialization when an    // exception propagates from a remoting server to the client.     protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,        System.Runtime.Serialization.StreamingContext context) { }}

Inner Exceptions

参考Inner Exceptions

using System;using System.IO;class ExceptionHandling{    public static void Main()    {        try        {            try            {                Console.WriteLine("Enter First Number");                int FN = Convert.ToInt32(Console.ReadLine());                Console.WriteLine("Enter Second Number");                int SN = Convert.ToInt32(Console.ReadLine());                int Result = FN / SN;                Console.WriteLine("Result = {0}", Result);            }            catch (Exception ex)            {                string filePath = @"C:\Sample Files\Log.txt";                if (File.Exists(filePath))                {                    StreamWriter sw = new StreamWriter(filePath);                    sw.Write(ex.GetType().Name + ex.Message + ex.StackTrace);                    sw.Close();                    Console.WriteLine("There is a problem! Plese try later");                }                else                {                    //把原来的异常作为一个参数传递给当前的exception                    throw new FileNotFoundException(filePath + " Does not Exist", ex);                }            }        }        catch (Exception ex)        {            //ex.Message获取当前的异常的信息            Console.WriteLine("Current or Outer Exception = {0}" + ex.Message);            //检查内部的exception是否为null            if(ex.InnerException != null)            {                Console.WriteLine("Inner Exception = {0}", ex.InnerException.Message);            }        }    }}

如果输入10/0,控制台输出如下的信息:

Enter First Number10Enter Second Number0Current or Outer Exception = {0}C:\Sample Files\Log.txt Does not ExistInner Exception = 尝试除以零。

catch 块

在下列条件要捕获异常:
1.很好地理解可能会引发异常的原因,并且可以实现特定的恢复,例如当捕获到 FileNotFoundException 对象时提示用户输入新的文件名。

2.可以创建和引发一个新的、更具体的异常

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

3.想要先对异常进行部分处理,然后再将其传递以进行额外处理。 在下面的示例中,catch 块用于在重新引发异常之前将条目添加到错误日志

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

创建和引发异常

异常用于指示在运行程序时发生了错误。 此时将创建一个描述错误的异常对象,然后使用 throw 关键字引发。 然后,运行时搜索最兼容的异常处理程序。
当存在下列一种或多种情况时,程序员应引发异常:

1.方法无法完成其定义的功能。例如,如果一种方法的参数具有无效的值:

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

2.根据对象的状态,对某个对象进行不适当的调用。一个示例可能是尝试写入只读文件。 在对象状态不允许操作的情况下,引发 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.    }}

3.方法的参数引发了异常。在这种情况下,应该捕获原始异常,并创建一个 ArgumentException 实例。 应将原始异常传递给 ArgumentException 的构造函数作为 InnerException 参数:

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;    }}