我正在处理一个处理大量 Sql 对象的类 - Connection、Command、DataAdapter、CommandBuilder 等。在多个实例中我们有这样的代码:
if( command != null )
{
command.Dispose();
}
if( dataAdapter != null )
{
dataAdapter.Dispose();
}
etc
我知道这在复制方面是相当不够的,但它已经开始有味道了。我认为它有味道的原因是因为在某些情况下该对象也被设置为 null。
if( command != null )
{
command.Dispose();
command = null;
}
如果可能的话,我很乐意摆脱重复。我想出了这个通用方法来处理对象并将其设置为 null。
private void DisposeObject<TDisposable>( ref TDisposable disposableObject )
where TDisposable : class, IDisposable
{
if( disposableObject != null )
{
disposableObject.Dispose();
disposableObject = null;
}
}
我的问题是...
- 这个通用函数是个坏主意吗?
- 是否需要将对象设置为
null
?
编辑:
我知道 using
语句,但是我不能总是使用它,因为我有一些成员变量需要持续超过一次调用。例如连接和事务对象。
谢谢!
最佳答案
您应该考虑是否可以使用 using
语句。
using (SqlCommand command = ...)
{
// ...
}
这确保当控制离开使用范围时,Dispose
在命令对象上被调用。与您自己编写清理代码相比,这有很多优点:
- 更简洁。
- 变量永远不会设置为 null - 它是在一条语句中声明和初始化的。
- 当对象被处置时,变量超出范围,因此您可以降低意外尝试访问已处置资源的风险。
- 它是异常安全的。
- 如果您嵌套 using 语句,那么资源自然会以正确的顺序放置(与创建它们的顺序相反)。
Is it necessary to set the object to null?
通常不需要在使用完变量后将其设置为空。重要的是您在使用完资源后调用 Dispose。如果你使用上面的模式,不仅没有必要将变量设置为 null——它会给出一个编译错误:
Cannot assign to 'c' because it is a 'using variable'
需要注意的一点是,using
只有在同一方法调用中获取和释放对象时才有效。如果您的资源需要在多个方法调用期间保持事件状态,则不能使用此模式。在这种情况下,您可能希望让您的类实现 IDisposable
并确保在调用 Dispose 方法时清理资源。在这种情况下,您将需要您编写的代码。在这种情况下将变量设置为 null
并没有错,但这并不重要,因为垃圾收集器无论如何都会正确清理内存。重要的是确保在调用 dispose 方法时释放您拥有的所有资源,并且您正在这样做。
一些实现细节:
- 您应该确保如果您的 Dispose 被调用两次,它不会抛出异常。您的效用函数可以正确处理这种情况。
- 您应该确保您对象上的相关方法引发
ObjectDisposedException
。如果您的元素已被处置。
关于c# - 处理处理 IDisposable 对象的通用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3189854/