奇怪的异常处理,try--finally

yzx110 2004-04-20 10:49:37
我开.Net书的时候都是说using语句块相当于try--finally块,可是在我的一个项目中我发现了一个问题。代码如下:
using(DataSet ds = GetDataSet())
{
//Some statement, may throw exception.
}
程序运行时在这里跑出了异常导致程序崩溃了,我纳闷了,这怎么可能??
于是我做了一个实验,代码如下:
using System;
namespace Console1
{
public class Maina
{
public static void Main(string[] args)
{
Test t = null;
try
{
t = new Test();
t.Init();
}
finally
{
Console.WriteLine("finally");
}
using(Test t1 = new Test())
{
t1.Init();
}
}
}

public class Test : IDisposable
{
public Test()
{
}

public void Init()
{
throw new Exception("Test constructor");
}
public void Dispose()
{
Console.WriteLine("Class test disposed.");
}
}
}
编译以上代码成功并执行,问题出现了,在try块中t.Init()跑出的异常没捕获到,导致程序崩溃。我查了一下MSDN,得到如下信息:

finally 块用于清除在 try 块中分配的任何资源。控制总是传递给 finally 块,与 try 块的存在方式无关。

于是我不明白了,为什么t.Init处想异常后没有执行到finally中的Console.WriteLine("finally")呢??如果这样的话,finally到底能干什么?
怎么书上和MSDN 上讲的都与实际不符呢?还是我的测试有问题?

由于try--finally的问题,导致了using的问题,也就是说在using块中如果有异常没有捕获的话,资源不会被释放。

不知大家有没有发现此问题,欢迎讨论。
...全文
48 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
showlie 2004-04-21
  • 打赏
  • 举报
回复
由于using子句中的对象必须执行IDisposable接口,如果对象不支持该接口,就会产生一个编译错误。而DataSet不支持IDisposable接口,因此会出现编译错误。
yzx110 2004-04-21
  • 打赏
  • 举报
回复
我再实验了一下,代码如下:
public class Maina
{
public static void Main(string[] args)
{
try
{
using(Test t1 = new Test())
{
t1.Init();
}
}
catch{Console.WriteLine("Exception");}
Console.ReadLine();
}
}

public class Test : IDisposable
{
public Test()
{
}

public void Init()
{
throw new Exception("Test constructor");
}
public void Dispose()
{
Console.WriteLine("Class test disposed.");
}
}

中与看到打印Class test diesposed了。

终于明白了,多谢大家!结贴了。
yzx110 2004-04-21
  • 打赏
  • 举报
回复
那就是说using适合用在比如像类库那样的场合,

而最终代码需要用try--catch[--finally] ??
Ninputer 2004-04-21
  • 打赏
  • 举报
回复
谁说发生异常就会崩溃呀?发生的异常难道不会用外层的try语句把它catch吗?异常的捕获总是一层一层进行的。using可以保证在发生异常时控制转移到外部的try语句中时,还能够清理using中初始化的变量。
yzx110 2004-04-21
  • 打赏
  • 举报
回复
谢谢大家讨论,我这里问题的焦点是using,
我的意思是using中如果有异常的话,那不是不能正常释放资源了?

如果是能的话,我就不知道这里using能干什么了,因为using里出现异常后直接导致程序崩溃,程序崩溃之后它占用的资源也是要被回收的,反正都会崩溃(因为用using和没用using都没有捕获异常)并且能清除资源,用不用using有什么区别呢?
xiangyangsunboy1 2004-04-20
  • 打赏
  • 举报
回复
try...catch ...finally
michleliu 2004-04-20
  • 打赏
  • 举报
回复
try...catch ...finally 一般是配套使用的。
异常处理应该在catch 中做,finally做的是最后你要处理的问题,无论如何都会走的!
brightheroes 2004-04-20
  • 打赏
  • 举报
回复
最常用的方法
SqlConnection con = .....;
try
{
con.open();
do something here
}
catch
{

}
finally
{
con.close();
}
Jinniu 2004-04-20
  • 打赏
  • 举报
回复
finally是try,catch后的模块,负责处理资源回收的事情!
Ninputer 2004-04-20
  • 打赏
  • 举报
回复
只有finaly不能捕获异常,一定要有catch或filter(C#不支持,只有VB才支持)才能捕获异常。
HNU 2004-04-20
  • 打赏
  • 举报
回复

你看看下面的代码


using System;
namespace Console1
{
public class Maina
{
public static void Main(string[] args)
{
Test t = null;
try
{
t = new Test();
t.Init();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}

finally
{
Console.WriteLine("finally");
}
try
{
using(Test t1 = new Test())
{
t1.Init();
}
}

catch(Exception e)
{
Console.WriteLine(e.Message);
}

Console.ReadLine();
}
}

public class Test : IDisposable
{
public Test()
{
}

public void Init()
{
throw new Exception("Test constructor");
}
public void Dispose()
{
Console.WriteLine("Class test disposed.");
}
}
}
bitsbird 2004-04-20
  • 打赏
  • 举报
回复
finally里释放资源
HNU 2004-04-20
  • 打赏
  • 举报
回复


catch(Exception e)
{
Console.WriteLine(e.ToString());
}
turnmissile 2004-04-20
  • 打赏
  • 举报
回复
//我开.Net书的时候都是说using语句块相当于try--finally块
他不光是一个try -catch- finally
还自动调用了object.Dispose();
//在try块中t.Init()跑出的异常没捕获到,导致程序崩溃
你要用catch(Exception exp),一场的类型由你判断
Ninputer 2004-04-20
  • 打赏
  • 举报
回复
正确的设计下,catch和finally很少同时使用。
JasminChen 2004-04-20
  • 打赏
  • 举报
回复
yzx110 (原振侠) :
异常发生时,执行将终止并且控制交给最近的异常处理程序。
t.Init()中引发的异常在该函数中没有相应的异常处理程序(如:catch语句块), 异常处理的控制权将交给调用它的函数Main(), 但Main()中也没有可以截获异常的处理程序,因此异常处理的控制权就被交给了系统。所以,Main()中Try语句后的finally块就没有机会执行了。
marvelstack 2004-04-20
  • 打赏
  • 举报
回复
finally
模块无论是否有异常都会执行。
如下面的函数,保证资源释放。
public static int ExecuteNonQuery(string strSql)
{
int count = -1;
OleDbConnection myConn = new OleDbConnection(strConn);
OleDbCommand myComm = new OleDbCommand(strSql,myConn);
try
{
myConn.Open();
count = myComm.ExecuteNonQuery();
}
catch(Exception e)
{

}
finally
{
if(myConn.State != ConnectionState.Closed)
myConn.Close();
myConn.Dispose();
myComm.Dispose();
}
return count;
}

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧