C#异常处理

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 Number
10
Enter Second Number
0
Current or Outer Exception = {0}C:\Sample Files\Log.txt Does not Exist
Inner 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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值