如果using语句抛出异常,我如何处置IDisposable对象?

时间:2022-12-05 19:55:05

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)。