1、首先要明白异常会在什么地方抛出,以及抛出异常的可能性有多大,如:
inStream = new FileStream(inFile, FileMode.Open, FileAccess.Read);
对于文件IO这样的代码,大家心里都会有一个概念,即它会抛出异常
但如:
byte[] value = Convert.FromBase64String(base64);
异常捕获可能就比较容易被忽视,base64是一个string,当base64不是一个标准的Base64编码字串时FromBase就会抛出异常
又如:
MemoryStream mStream = new MemoryStream();
这样的内存分配代码,一般情况不要捕获异常,Windows的内存机制决定了以上代码出现内存不足的情况很小
2、捕获之后要作什么,或者说try之后要作什么操作
Win32API有一种机制,就是利用返回值来说明调用是否成功,比如在返回值不可能是负值的情况下返回-1来说明调用失败,而调用方可以通过GetLastError来获取更具体的异常信息
在C#中并没有这样的机制,或者说这是一种“落后”了的机制,并且在类的方法中捕获并吃掉任何可能发生的异常也会使编码过程变得繁琐,建议的作法是让调用代码来处理异常
在调用代来捕获异常并不意味着在类方法中就不要捕获异常了,比如以下代码:
public static int GetFileSize(string fileName) { FileStream fStream = null; long fileSize = -1; try { fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); //do something for fStream... fileSize = fStream.Length; } finally { if (fStream != null) fStream.Close(); } //注意,当异常发生时return 不会被执行 return fileSize; }
如果GetFileSize的调用方在异常发生时需要知道具体的异常信息,然后显示给最终用户,单纯的在GetFileSize内部Catch掉异常并返回-1显然不能满足这个要求,但GetFileSize内部也不能不捕获异常而完全让GetFileSize的调用方来处理异常,因为FileStream可能是Open的,而只是后继操作产生了异常,也就是说,即使将异常交由调用方处理,也应在必要的时候在内部加入异常捕获代码作一些收尾工作,比如这里的正确释放资源,以上代码的另一种形式是:
public static int GetFileSize(string fileName) { FileStream fStream = null; long fileSize = -1; try { fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); //do something for fStream... fileSize = fStream.Length; } catch(Exception ex) { Trace.WriteLine(ex.Message); if (fStream != null) fStream.Close(); } //注意,当异常发生时return 不会被执行 return fileSize; }