一、为异常寻找处理程序
首先先放一张处理异常的一般法则图片,这是异常发生后系统寻找异常处理程序规则的流程:
![](https://img-blog.csdnimg.cn/20190222151034709.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ltZ19HdW8=,size_16,color_FFFFFF,t_70)
以下代码是个人用来学习记录,功能是看懂try、catch语句可以看懂在搜索调用栈来寻找一个异常处理程序的顺序。
/*
* 时间:2019年1月23日15点34分
* 功能:看懂搜索try\catch语句搜索调用栈寻找一个异常处理程序的顺序
*/
using System;
/// <summary>
/// 包含两个方法的类型,其中B类型是异常的
/// </summary>
class MyClass
{
public void A()
{
try
{
B();
}
catch (NullReferenceException)
{
Console.WriteLine("catch clause in A()");
}
finally
{
Console.WriteLine("finally clause in A()");
}
}
public void B()
{
int x = 10, y = 0;
try
{
x /= y; //异常,异常类型:DivideByZeroException
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("catch clause in B()");
}
finally
{
Console.WriteLine("finally clause in B()");
}
}
}
/// <summary>
/// 主程序
/// </summary>
class Program
{
static void Main()
{
MyClass myClass = new MyClass();
try
{
myClass.A();
}
catch (DivideByZeroException)
{
Console.WriteLine("catch clause in Main()");
}
finally
{
Console.WriteLine("finally clause in Main()");
}
Console.WriteLine("After try statement in Main()");
Console.WriteLine(" --------------- Keep Running");
Console.ReadKey();
}
}
/* 程序运行结果
-----------------------------------------
finally clause in B()
finally clause in A()
catch clause in Main()
finally clause in Main()
After try statement in Main()
--------------- Keep Running
-----------------------------------------
*/
二、异常抛出
可以使用throw语句显式地引发一个异常,下面的代码定义了一个名称为PrintArg()的方法,它带一个string参数并打印出来。在try块的内部,首先做检查以确定该参数不是null。如果是null,它创建一个ArgumentNullException实例并抛出它。该异常在catch语句中捕获,并且该出错消息被打印。Main调用该方法两次:一次用null参数,一次用一个有效参数。
/*
* 时间:2019年1月23日15点57分
* 功能:抛出异常
*/
using System;
/// <summary>
/// 抛出异常
/// </summary>
class MyClass
{
public static void PrintArg(string Arg)
{
try
{
if (null == Arg)
{
ArgumentNullException myEx = new ArgumentNullException("Arg");
throw myEx;
}
Console.WriteLine(Arg);
}
catch(ArgumentNullException e)
{
Console.WriteLine("Message: {0}",e.Message);
}
}
}
/// <summary>
/// 主程序
/// </summary>
class Program
{
static void Main()
{
string s = null;
MyClass.PrintArg(s);
MyClass.PrintArg("Hello!");
Console.ReadKey();
}
}
/* 程序运行结果
--------------------------------------------
Message: Value cannot be null.
Parameter name: Arg
Hello!
--------------------------------------------
*/
为什么这里需要写程序时主动让它参数为null就抛出异常?
因为类似于这样的例子,参数为null程序运行时候系统并不认为这是一个异常,但是会对结果产生很大的影响。而我们写程序的时候控制让它参数为空就抛出异常,这样可以尽最大可能保证程序运行时候的稳定性,归根结底还是让程序不能自动识别异常的时候手动抛出。
三、不带异常对象的抛出
throw语句还可以不带异常对象使用,在catch语句块内部。
1、这种形式重新抛出当前异常,系统继续它的搜索,为该异常寻找另外的处理代码;
2、这种形式只能用在catch语句内部
/*
* 时间:2019年1月23日16点10分
* 功能:不带异常对象的抛出
*/
using System;
/// <summary>
/// 抛出异常
/// </summary>
class MyClass
{
public static void PrintArg(string Arg)
{
try
{
try
{
if (null == Arg)
{
ArgumentNullException myEx = new ArgumentNullException("Arg"); //提供null参数的名称
throw myEx;
}
Console.WriteLine(Arg);
}
catch (ArgumentNullException e)
{
Console.WriteLine("Inner Catch: {0}",e.Message);
throw; //重新抛出异常,没有附带参数
}
}
catch
{
Console.WriteLine("Other catch: Handing an Exception.");
}
}
}
/// <summary>
/// 主程序
/// </summary>
class Program
{
static void Main()
{
string s = null;
MyClass.PrintArg(s);
Console.ReadKey();
}
}
/* 程序运行结果
--------------------------------------------
Inner Catch: Value cannot be null.
Parameter name: Arg
Other catch: Handing an Exception.
--------------------------------------------
*/