最近对异常处理比较气愤。因为引发了一些BUG……
“异常处理不是用来避免BUG的吗?”,他们这样说的,但是异常处理确实引发了BUG。
目录
如果代码需要优雅,你为什么不去跳芭蕾?
看看下面的代码:
try{StreamReader streamReader = new StreamReader(file_name);n = long.Parse(streamReader.ReadLine());。。。。。。streamReader.Close();}catch (Exception ex){Log("读取文件出错:" + ex);WriteFile();}
打开文件、读文件、关闭文件,如果异常就重新生成文件,“WriteFile();”也是相同的逻辑,操作同一个文件,只不过换成了StreamWriter对象。
看起来什么问题都没有,如果文件不存在(比如第一次运行),会抛出异常,然后进入异常处理,大部分情况下确实如此,直到我修改了文件格式,导致读文件出错同时异常处理中生成文件的代码也出错——程序BUG了。
异常信息表示,第一次是读文件异常(因为已经到达文件尾,能够理解,因为格式变了),第二次是打开文件异常,文件被占用,这是为什么?
仔细分析一下执行流程:
try{StreamReader streamReader = new StreamReader(file_name);n = long.Parse(streamReader.ReadLine());------此处异常,跳转到异常处理。。。。。。streamReader.Close();------此句被跳过,文件仍然是打开的}catch (Exception ex){Log("读取文件出错:" + ex);WriteFile();------这里无法再次打开文件}
原因不复杂,就是因为异常导致后面的文件关闭没有执行。
为了解决这个BUG,必须修改代码:
StreamReader streamReader = null;------在try块之外定义变量try{streamReader = new StreamReader(file_name);n = long.Parse(streamReader.ReadLine());。。。。。。streamReader.Close();}catch (Exception ex){if (null != streamReader) streamReader.Close();------先关闭文件Log("读取文件出错:" + ex);WriteFile();}
这样BUG就解决了。很easy。
但是,如果需要这样复杂的代码结构,异常处理跟判断返回值相比有什么好处呢?好好的一段代码硬被分成三块(变量定义、正常处理、出错处理),这和goto有什么区别?
异常处理就是为了讨好懒惰的程序员,不用写返回值判断,统统一个catch解决,程序质量大幅提高:虽然结果仍然不正确,但是不会异常退出了。这不是掩耳盗铃吗?
如果代码需要优雅,你为什么不去跳芭蕾?
(这里是结束)