浅尝EffectiveCSharp_8

Item 15: Utilize using and try/finally for Resource Cleanup 使用using 和 try/finally 进行资源清理

使用非托管系统资源的类型应该用Dispose()方法来释放。.NET环境的规则是:使用该类型的代码对它有释放的责任,而不是该类型或者系统。The  rules of the .NET environment make that the responsibility of the code that uses the type, not the responsibility of the type or the system.因此,当你使用的方法有Dispose()方法,那么你应该记得调用Dispose()方法来释放它。保证Dispose()的最好方法就是使用using声明或者是try/finally块。
●C#语言设计者知道明确的释放资源会是a common task。他们增加了关键字来使它更简单。加入你写了一下代码

 
  
public void ExecuteCommand( string connString, string commandString)
{
SqlConnection myConnection
= new SqlConnection(connString);
SqlCommand mySqlCommand
= new SqlCommand(commandString,myConnection);
myConnection.Open();
mySqlCommand.ExecuteNonQuery();
}

 在这个例子中,两个可释放对象没有惊醒正确的清理:SqlConnection and SqlCommand。这些对象依然存在在内存中,直到finalizers被调用。下面是一个修改的例子

 
  
public void ExecuteCommand( string connString, string commandString)
{
SqlConnection myConnection
= new SqlConnection(connString);
SqlCommand mySqlCommand
= new SqlCommand(commandString,myConnection);
myConnection.Open();
mySqlCommand.ExecuteNonQuery();
mySqlCommand.Dispose();
myConnection.Dispose();
}

这个已经比较好了,除非SQL执行时出现了异常被抛出。那样的话,调用的Dispose()就不会发生。下面使用using声明来保证Dispose()被调用

 
  
public void ExecuteCommand( string connString, string commandString)
{
using (SqlConnection myConnection = new SqlConnection(connString))
{
using (SqlCommand mySqlCommand = new SqlCommand(commandString, myConnection))
{
myConnection.Open();
mySqlCommand.ExecuteNonQuery();
}
}
}

无论你什么时候在函数中使用一个可释放 的对象,使用using是保证对象释放的最简单方法。

 

●如果你对一个不支持IDisposable接口的变量使用using,编译器会产生一个错误。比如:如果obj实现IDisposable接口,using声明就会产生清楚代码。

 
  
// Does not compile:
// String is sealed, and does not support IDisposable.
using ( string msg = " This is a message " )
Console.WriteLine(msg);
using声明只有在编译时类型支持IDisposable接口的情况下有用。
// Does not compile.
// Object does not support IDisposable.
using ( object obj = Factory.CreateResource())
Console.WriteLine(obj.ToString());

// The correct fix.
// Object may or may not support IDisposable.
object obj = Factory.CreateResource();
using (obj as IDisposable)
Console.WriteLine(obj.ToString());

 

●using声明是一个套一个。现在来看看try/catch块

 
  
public void ExecuteCommand( string connString,
string commandString)
{
SqlConnection myConnection
= null ;
SqlCommand mySqlCommand
= null ;
try
{
myConnection
= new SqlConnection(connString);
mySqlCommand
= new SqlCommand(commandString,myConnection);
myConnection.Open();
mySqlCommand.ExecuteNonQuery();
}
finally
{
if (mySqlCommand != null )
mySqlCommand.Dispose();
if (myConnection != null )
myConnection.Dispose();
}
}

 现在已经解决了两个非常显著的问题,但是这里还有点细微的差别。有的类型既支持Dispose方法也支持Close方法来释放对象。SqlConnection就是这样的一种类型。你也可以这样关闭SqlConnection:

 
  
public void ExecuteCommand( string connString,
string commandString)
{
SqlConnection myConnection
= null ;
try
{
myConnection
= new SqlConnection(connString);
SqlCommand mySqlCommand
= new SqlCommand(commandString,myConnection);
myConnection.Open();
mySqlCommand.ExecuteNonQuery();
}
finally
{
if (myConnection != null )
myConnection.Close();
}
}

 这里connection并没有被关闭。Dispose方法和Close方法并不完全一样,Dispose在释放了资源后,还通知了GC去处理,它调用了GC.SuppressFinalize()。而Close没有这么做,因此对象依然在finalization队列。如果你能选择,Dispose() is better than Close().

 


 

转载于:https://www.cnblogs.com/TivonStone/archive/2010/06/11/1756280.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值