How can I make sure in the following code snippet that IDataReader
is disposed of if ExecuteReader
throws an exception?
如果ExecuteReader抛出异常,如何在以下代码片段中确保IDataReader被丢弃?
using (IDataReader rdr = cmd.ExecuteReader())
{
// use it
}
It makes sense to me that the using
syntatic sugar does not call Dispose (since there is no instance to call it on). However, how can I be sure that the scarce resources that are normally allocated by classes that implement IDisposable will be releases?
对我来说,使用合成糖不会调用Dispose(因为没有实例可以调用它)是有道理的。但是,我怎样才能确定通常由实现IDisposable的类分配的稀缺资源将被释放?
4 个解决方案
#1
If ExecuteReader, in your example, throws an exception it never returns anything. It is then up to the implementation of ExecuteReader to dispose of anything created before the exception.
如果在您的示例中,ExecuteReader抛出异常,则它永远不会返回任何内容。然后由ExecuteReader实现,以处理在异常之前创建的任何内容。
#2
If the constructor of an object fails to run then you do not have an object that needs to be disposed.
如果对象的构造函数无法运行,那么您没有需要处理的对象。
If you are writing a constructor which could throw an exception, you had better make sure you clean up anything you need to by using using
or try-catch block.
如果您正在编写可能抛出异常的构造函数,那么最好确保使用using或try-catch块清理所需的任何内容。
In your IDataReader example, it is sufficient to simply dispose of the command object if the cmd.ExecuteReader()
method call fails.
在IDataReader示例中,如果cmd.ExecuteReader()方法调用失败,则只需处理命令对象就足够了。
#3
How about moving the code that does the initialization outside the constructor into a separate function. In essence you'll have
如何将在构造函数外部执行初始化的代码移动到单独的函数中。从本质上说,你将拥有
using (var tc = new TestClass())
{
tc.Initialize(); // setup the object. acquire expensive resources here, etc.
..more code ..
}
#4
I thought that the using statement was translated to the IL that is similar to:
我认为using语句被翻译成IL,类似于:
try
{
}
finally
{
disposableUsedObject.Dispose();
}
So, I would think that in normal circumstances, the Dispose should be called ?
那么,我认为在正常情况下,应该调用Dispose?
Also, you should not throw exceptions inside the constructor , as users will not expect that an exception will be thrown when they instantiate an object. I would move the initialization logic that can throw an exception to another method (Initialize) that has to be called after instantiating the object.
此外,您不应该在构造函数中抛出异常,因为用户在实例化对象时不会期望抛出异常。我会移动初始化逻辑,该逻辑可以将异常抛给另一个在实例化对象后必须调用的方法(Initialize)。
#1
If ExecuteReader, in your example, throws an exception it never returns anything. It is then up to the implementation of ExecuteReader to dispose of anything created before the exception.
如果在您的示例中,ExecuteReader抛出异常,则它永远不会返回任何内容。然后由ExecuteReader实现,以处理在异常之前创建的任何内容。
#2
If the constructor of an object fails to run then you do not have an object that needs to be disposed.
如果对象的构造函数无法运行,那么您没有需要处理的对象。
If you are writing a constructor which could throw an exception, you had better make sure you clean up anything you need to by using using
or try-catch block.
如果您正在编写可能抛出异常的构造函数,那么最好确保使用using或try-catch块清理所需的任何内容。
In your IDataReader example, it is sufficient to simply dispose of the command object if the cmd.ExecuteReader()
method call fails.
在IDataReader示例中,如果cmd.ExecuteReader()方法调用失败,则只需处理命令对象就足够了。
#3
How about moving the code that does the initialization outside the constructor into a separate function. In essence you'll have
如何将在构造函数外部执行初始化的代码移动到单独的函数中。从本质上说,你将拥有
using (var tc = new TestClass())
{
tc.Initialize(); // setup the object. acquire expensive resources here, etc.
..more code ..
}
#4
I thought that the using statement was translated to the IL that is similar to:
我认为using语句被翻译成IL,类似于:
try
{
}
finally
{
disposableUsedObject.Dispose();
}
So, I would think that in normal circumstances, the Dispose should be called ?
那么,我认为在正常情况下,应该调用Dispose?
Also, you should not throw exceptions inside the constructor , as users will not expect that an exception will be thrown when they instantiate an object. I would move the initialization logic that can throw an exception to another method (Initialize) that has to be called after instantiating the object.
此外,您不应该在构造函数中抛出异常,因为用户在实例化对象时不会期望抛出异常。我会移动初始化逻辑,该逻辑可以将异常抛给另一个在实例化对象后必须调用的方法(Initialize)。