12.1 异常概述
异常:异常就是程序执行期间发生的问题。异常发生的原因不一定都在程序上,比如用户输入非法数据,读取不存在的文件等等;
如:
class Program { static void Main(string[] args) { Console.WriteLine("输入分母"); int de = Convert.ToUInt16(Console.ReadLine());//如果Console.ReadLine()无法转为数字,产生异常 double result = 100 / de; //de=0如果产生异常 Console.WriteLine("100/{}=",de); Console.ReadKey(); } }
12.2捕获异常 try...catch...
C#中使用 try...catch来捕获异常并处理,我们 将可能出现异常的语句放在try语句块中,把异常发生后的处理代码放在catch块中;
class Program { static void Main(string[] args) { Console.WriteLine("输入分母"); try // try语句块 { int de = Convert.ToUInt16(Console.ReadLine()); double result = 100 / de; Console.WriteLine("100/{}=", de); Console.ReadKey(); } catch (DivideByZeroException) // catch语句块,可有对多 { Console.WriteLine("DivideByZeroException"); Console.ReadKey(); } catch (FormatException) { Console.WriteLine("FormatException"); Console.ReadKey(); } } }
12.3 try...catch...final
(1)在某些问题上,无论是否出现 异常,都有些收尾工作需要处理,此时就用到了finally,如果加上了finally语句块,则finally语句块无论程序是否发生异常都会执行;
(类似于资源释放等代码通常放在fanally里面,表示是否发生异常,都释放资源);
try catch finally 执行过程如下:
eg:
static void Main(string[] args) { Console.WriteLine("输入分母"); try { int de = Convert.ToUInt16(Console.ReadLine()); double result = 100 / de; Console.WriteLine("100/{}=", de); Console.ReadKey(); } catch (DivideByZeroException) { Console.WriteLine("DivideByZeroException"); Console.ReadKey(); } catch (FormatException) { Console.WriteLine("FormatException"); Console.ReadKey(); } finally { //finally,无论是否发生异常,finally都会执行 Console.WriteLine("是否发生异常,finally都会执行"); Console.ReadKey(); } }
(2)规则
(a)如果try语句后有catch语句,则finally是可选的;
(b)如果try语句后面没有cactch语句,则必须加finally语句(也就是catch或者finally必须有一个):注意finally只能有一个
(c)如果有catch语句,则finally必须放在所欲catch语句后面;
12.4 抛出异常
.NET 可以用try自动检测异常,但是有时候我们需要人工抛出异常。此时就需要throw语句;
throw使用方法:
static void Main(string[] args) { Console.WriteLine("输入一个1到10之间的数字"); int i; try { i=Convert.ToInt16(Console.ReadLine()); if (i>10||i<1) { throw new IndexOutOfRangeException(); //抛出系统以异常,注意IndexOutOfRangeException 是系统定义的异常类
} else { Console.WriteLine("输入正确"); } } catch (IndexOutOfRangeException) { Console.WriteLine("超出范围"); }
12.5 .NET 中的异常类
(1)异常类没有固定的名字空间,哪个类发生异常,异常就放在哪个名字空间;
(2).NET中所有的异常类都派生于SystemException,而用户自定义的异常类都派生于ApplicationException
(3)由于派生类属于基类,所以有多catch语句时候,一定要按照从一般到具体的顺序从上到下排列,基类必须放在最后,
否则派生类的catch语句块可能永远没有机会执行了(目前最新的.NET直接报错无法编译);
catch (SystemException) { } catch (DivideByZeroException) //错误 上一个 catch 子句已经捕获了此类型或超类型 { Console.WriteLine("DivideByZeroException"); Console.ReadKey(); } catch (FormatException) { Console.WriteLine("FormatException"); Console.ReadKey(); }
(4)我们可以不给catch指定异常类型,此时catch则可以捕获任何异常;
try { int de = Convert.ToUInt16(Console.ReadLine()); } catch { }
12.6 异常类的属性:
Exception类和其他类一样有几个公共属性,比较重要的是以下两个;
Message:用于描述异常产生的原因;
Stacktrace:用于描述异常的堆栈信息,即异常发生的位置;
可以在catch语句声明一个异常类的对象,可以利用这个对象使用Exception的属性
eg:
try { int de = Convert.ToUInt16(Console.ReadLine()); double result = 100 / de; Console.WriteLine("100/{}=", de); Console.ReadKey(); } catch (DivideByZeroException e) //声明异常形参 { Console.WriteLine("Message:" + e.Message); //异常信息 Console.WriteLine("StackTrace" + e.StackTrace); //异常位置 Console.WriteLine("Source" + e.Source); Console.ReadKey(); }
12.7 自定义异常类:
我们也可以自己定义异常类,用户定义的异常类都需直接或者间接继承于ApplacationException类
//定义自己异常类 class NegativeNumberExcption:ApplicationException { public NegativeNumberExcption():base("对负值就行了非法操作") { } public NegativeNumberExcption(string message) : base(message) { } } class Program { static void Main(string[] args) { Console.WriteLine("数字"); try { int de = Convert.ToInt16(Console.ReadLine()); double resule = 0; if (de < 0) { throw new NegativeNumberExcption("负数不能开平方"); } else resule = Math.Sqrt(de); } catch (FormatException) { } catch (NegativeNumberExcption w) { Console.WriteLine(w.Message); Console.WriteLine(w.StackTrace); } Console.ReadLine(); } }