异常的处理
1 如何针对不同的异常进行捕捉
2 如何使用Conditional特性
3 如何避免类型转换时的异常
异常的处理
C#中一个try块可以有多个catch块,每个catch块可以针对特别的异常进行特别的处理。但是安全起见,最后应该添加一个对象Exception类型的异常捕捉的catch块,以保证没有异常被毫无处理地抛出。
实例代码如下:
class CatchException { static void Main(string[] args) { CatchException ce = new CatchException(); ce.RiskWork(); Console.Read(); } public void RiskWork() { try { /* 一些预计可能产生异常的代码 */ } catch (NullReferenceException ex) { HandleExpectedException(ex); } catch (ArgumentException ex) { HandleExpectedException(ex); } catch (FileNotFoundException ex) { HandleError(ex); } catch (Exception ex) { HandleCrash(ex); } } //这里处理预计可能会发生的,不属于错误范畴的异常 private void HandleExpectedException(Exception ex) { Console.WriteLine(ex.ToString()); } //这里处理在系统出错时可能会发生的,比较严重的异常 private void HandleError(Exception ex) { Console.WriteLine(ex.ToString()); throw ex; //严重的异常,抛到上层处理 } private void HandleCrash(Exception ex) { Console.WriteLine(ex.ToString()); System.Threading.Thread.CurrentThread.Abort(); } }
Conditional特性用于编写在某个特定编译版本中运行的方法,通常它编写一些在Debug版本中支持测试的方法。当版本不匹配时,编译器会把Conditional特性的方法内容置空。
示例代码:
//含有两个成员,生日和身份证 //身份证的第6位到第14位必须是生日 //身份证必须是18位 public class People { private DateTime _birthday; private String _id; public DateTime Birthday { set { _birthday = value; if (!Check()) throw new ArgumentException(); } get { Debug(); return _birthday; } } public String ID { set { _id = value; if (!Check()) throw new ArgumentException(); } get { Debug(); return _id; } } public People(String id,DateTime birthday) { _id = id; _birthday = birthday; Check(); Debug(); } //只希望在DEBUG版本中出现 [Conditional("DEBUG")] protected void Debug() { Console.WriteLine(_birthday.ToString("yyyy-MM-dd")); Console.WriteLine(_id); } //检查是否符合业务逻辑 //在所有版本中都需要 protected bool Check() { if (_id.Length != 18 || _id.Substring(6, 8) != _birthday.ToString("yyyyMMdd")) return false; return true; } static void Main(string[] args) { try { People p = new People("310101198008010031", new DateTime(1980, 8, 1)); p.ID = "310101198709080031"; } catch (ArgumentException ex) { Console.WriteLine(ex.GetType().ToString()); } finally { Console.Read(); } } }
下面分别是Debug版本和Release版本的输出:
Debug版本:
1980-08-01
310101198008010031
System.ArgumentException
Release版本:
System.ArgumentException
用 is 和 as 语句代替强制类型转换,可以有效避免InvalidCaseException 异常,执行效率相对较高。
示例代码:
public class UseIsAs { static void Main(string[] args) { Base b = new Base(); Son s = new Son(); String mystring = "我的类型不匹配"; DateTime n = DateTime.Now; //对三套方法进行验证,结果应该是一样的 CastToBase1(b); CastToBase1(s); CastToBase1(mystring); CastToBase1(n); CastToBase2(b); CastToBase2(s); CastToBase2(mystring); CastToBase2(n); CastToBase3(b); CastToBase3(s); CastToBase3(mystring); CastToBase3(n); Console.Read(); } //用is进行转换 static void CastToBase1(Object o) { if (o is Base) { Base b = (Base)o; Console.WriteLine(b.ToString()); } else Console.WriteLine("转换失败"); } //用as进行转换 static void CastToBase2(Object o) { Base b = o as Base; if(b!=null) Console.WriteLine(b.ToString()); else Console.WriteLine("转换失败"); } static void CastToBase3(Object o) { try { Base b = (Base)o; Console.WriteLine(b.ToString()); } catch { Console.WriteLine("转换失败"); } } } /// <summary> /// 简单的基类和子类 /// </summary> public class Base { public override string ToString() { return "我是基类"; } } public class Son : Base { public override string ToString() { return "我是子类"; } }
输出结果:
我是基类
我是子类
转换失败
转换失败
我是基类
我是子类
转换失败
转换失败
我是基类
我是子类
转换失败
转换失败
转载请注明出处: