分享
 
 
 

C#中的异常处理(简单)二

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

三、finally?

解决释放问题的方法依靠你现在使用的语言。在C++中,你可以使用构建于堆栈上的析构函数。Java中,你能构使用finally程序块。C#允许你创造自定义的结构类型但是不允许结构中的析构函数(只是因为一个C#析构函数其实是一个Finally方法,Finally被垃圾回收器调用。结构类,是一种值类型,并不归属于垃圾回收器回收的范围)。因而,只是在开始,C#必须追循Java的道路,使用finally程序块。首先,我们的finally程序块开起来如下:

private static char[] ReadSource(string filename)

{

try

{

FileInfo file = new FileInfo(filename);

int length = (int)file.Length;

char[] source = new char[length];

TextReader reader = file.OpenText();

reader.Read(source, 0, length);

}

finally

{

reader.Close();

}

return source;

}

这个版本不得不引入一个try程序块(既然一个finally程序快必须跟随在一个try程序块后),这将是一个合理的解决方案,如果它奏效的话。但是,它没有做到。问题是try程序块构建成一个范围,所以在finally程序块中的reader并不在这个范围内并且返回语句中的source也不在这个范围。

finally?

为了解决这个问题,你不得不将reader和source的声明移到try程序块的外面,第二次尝试如下:

private static char[] ReadSource(string filename)

{

TextReader reader;

char[] source;

try

{

FileInfo file = new FileInfo(filename);

int length = (int)file.Length;

source = new char[length];

reader = file.OpenText();

reader.Read(source, 0, length);

}

finally

{

reader.Close();

}

return source;

}

这个版本将reader和source的声明移到了try程序块的外面,接着指派给reader和source但没有初始化它们。这是和开始的“理想”版本不同的另外一个地方(出现两个多余行)。然而,你可能认为如果它工作,那将是一个合理的解决方案。但是它没有。问题是委派并不等同于初始化及让编译器知道它。如果在reader被分配之前出现一个异常,这是在finally程序块中对reader.close()的调用

将根据没有被分配的reader,C#,像Java一样,不允许那样。

finally?

很明显,你必须要初始化reader,第三次尝试如下:

private static char[] ReadSource(string filename)

{

TextReader reader = null;

char[] source;

try

{

FileInfo file = new FileInfo(filename);

int length = (int)file.Length;

source = new char[length];

reader = file.OpenText();

reader.Read(source, 0, length);

}

finally

{

reader.Close();

}

return source;

}

这个版本引入了空值,这没有出现在最初的“理想版本”中。不过,如果你仍然认为如果它起作用这将是一个合理的解决方式,然而它不是(虽然它能通过编译)。问题是你在调用reader.close()的时候很容易抛出NullReferenceException异常。

finally?

一种解决方法是对eader.close()方法进行保护,下面做第四次尝试:

private static char[] ReadSource(string filename)

{

TextReader reader = null;

char[] source;

try

{

FileInfo file = new FileInfo(filename);

int length = (int)file.Length;

source = new char[length];

reader = file.OpenText();

reader.Read(source, 0, length);

}

finally

{

if (reader != null)

{

reader.Close();

}

}

return source;

}

当然,对reader.close()的保护并不是ReadSource的理想版本。但是,如果仅从它的效果上看,这将是一个合理的版本。最终,工作。它和最初的版本已经大不相同。稍微努力,你能复用下面这段代码:

private static char[] ReadSource(string filename)

{

FileInfo file = new FileInfo(filename);

int length = (int)file.Length;

char[] source = new char[length];

TextReader reader = file.OpenText();

try

{

reader.Read(source, 0, length);

}

finally

{

if (reader != null)

{

reader.Close();

}

}

return source;

}

在某些情况下,你可以在finally程序块中对可能出现空值进行判断(上面就是一个这样的例子),但是一般说来,你最好还是在finally程序块中判断一下(考虑到如果file.OpenText返回空值,或者如果reader被放进了try程序块中,或者reader作为ref/out参数被传递到try程序块中)。你不得不增加一个try程序块,一个finally程序块,和一个if防护。如果你正在使用Java,你不得不每一次都去做这些事情。在那里是个最大的问题。如果这个解决方案非常令人厌烦且完全偏离于最初的“完美”方案,这没有关系,你能够将这些异常提取到一块。在Java中,你不能这么做。遇到异常,Java将停止运行,而C#则将继续。

四、using语句

在C#中,最接近于“理想”版本的是使用using语句:

private static char[] ReadSource(string filename)

{

FileInfo file = new FileInfo(filename);

int length = (int)file.Length;

char[] source = new char[length];

using (TextReader reader = file.OpenText())

{

reader.Read(source, 0, length);

}

return source;

}

Reader将会被恰当的关闭。简单说来,using语句有大量的特征能够改善开始的“理想”版本。首先,我们看一下它内在的运行机制到底是怎样的。

using语句转换

C#ECMA标准描述using声明:

using (type variable = initialization)

embeddedStatement

它等同于

{

type variable = initialization;

try

{

embeddedStatement

}

finally

{

if (variable != null)

{

((IDisposable)variable).Dispose();

}

}

}

它依赖于System命名空间中的IDisposable接口:

namespace System

{

public interface IDisposable

{

void Dispose();

}

}

注意:finally程序块中的牵制转换意味着,这个变量必须是一个支持IDisposable接口的类(通过继承或转换操作)。如果它不是,你就会得到一个编译时错误。

using TextReader 转换

不出乎意料,TextReader支持IDisposable接口,并且实现了Dispose来调用关闭。这意味着:

using (TextReader reader = file.OpenText())

{

reader.Read(source, 0, length);

}

相当于下面:

{

TextReader reader = file.OpenText();

try

{

reader.Read(source, 0, length);

}

finally

{

if (reader != null)

{

((IDisposable)reader).Dispose();

}

}

}

除了对IDisposable的强制转换外,这和最通用的Java解决方式是相同的。这个强制转换是必须的因为这是一个通用解决方式。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有