C#中的异常机制

C#中的异常机制主要依赖于几个关键字,try,catch,finally和throw。合理实现异常机制有利于程序健壮性,不至于在一个异常抛出就造成程序崩溃。
 

最简单的情况

C#使用try来包括可能会抛出异常的代码块,之后可以接catch,可以接finally,也可以接catch和finally,但是不能一个都没有。catch代码块能够处理抛出来的异常,而finally主要是为了执行一段无论异常抛出与否都会执行的代码。

			try
            {
                int i = 10;
                int j = 0;
                int result = i / j;
            }
            catch
            {
                Console.WriteLine("error catch");
            }
            finally
            {
                Console.WriteLine("Finally");
            }

这段代码会输出error catchFinally因为有异常抛出,所以catch代码块中的代码被执行,同时finally代码块也会执行。
另一方面,如果我们把上面的j改为其他非0数字,没有异常抛出,那么只有finally代码块里面的代码会执行,因为无论有没有异常,finally都是确保执行的。
 

当return遇上finally

在使用finally的时候,有一种情况比较迷惑人,如果finally之前的try里面,有return,那么finally还执行吗?
理解这一点的关键,是要明白,finally有两个特性。

  • 当函数堆栈没有退出的时候,Finally代码块跟其他代码块一样,正常执行。

  • 当函数堆栈退出的时候,无论是因为异常抛出而退出还是使用return退出,finally都会确保执行,但是yield return不会触发finally。

理解了这两点,我们就很容易知道下面代码的行为。

		void FinallyTest()
        {
            try
            {
                return;
            }
            finally
            {
                Console.WriteLine("finally executed");
            }
        }
		
		FinallyTest(); //这次调用会输出finally executed

		public static IEnumerable<string> GetStrings()
        {
            try
            {
                yield return "a";
                yield return "b";
                yield return "c";
                yield return "d";
            }
            finally
            {
                Console.WriteLine("finally executed"); //在使用foreach遍历的时候,yield return 并没有触发finally代码块
            }
        }

为什么要使用throw

throw关键字用于重新抛出异常,通常当我们希望在不同的函数层次中依次处理一个异常的时候,我们就需要使用throw关键字,常见做法为,底层函数捕获异常,进行一些处理,之后抛出这个异常给上层函数,上层函数继续这个操作,这样不同层次的函数可以选择自己想要的异常处理操作。

		void OutterMethod()
        {
            try
            {
                InnerMethod();
            }
            catch
            {
                Console.WriteLine("Caught in outer");
            }
        }

        void InnerMethod()
        {
            try
            {
                int i = 10;
                int j = 0;
                int result = i / j;
            }
            catch(Exception e)
            {
                Console.WriteLine("Caught in inner");
                throw;
            }
        }

在上面这段代码中,我们可以看到,innerMethod捕捉到了异常之后,进行了自己的处理再抛出,这样上层代码有机会再针对这个异常进行处理。使用throw的时候有两种方式,一种是throw,一种是throw exception,它们之间的区别在于:

  • throw保留之前的异常堆栈信息,而且不需要catch中的Exception实例。

  • throw e新建异常堆栈信息,这样堆栈信息的起始点就是throw e的地方而不是原始异常发生的地方。

根据不同的需求,选择适合的方式使用throw。

猜你喜欢

转载自blog.csdn.net/deatharthas/article/details/88600636