如何在我的函数中返回一个可丢弃的对象,以确保它在using块中正常工作?在我的函数中,我希望对可丢弃的对象执行操作,并考虑错误,这会使问题复杂化。
到目前为止,我的代码类似于以下代码:
DBHandle GetDB()
{
/* // I can't do this, because the using block would dispose of my object within this function
using( var db = DatabaseObj.GetHandle() )
{
db.Open();
return db;
}
*/
var db = DatabaseObj.GetHandle();
try
{
db.Open();
return db;
}
catch (Exception ex)
{
db.Dispose();
throw ex;
}
}
// In other code:
using( var obj = GetDB() ){ /* ... */ }编辑:与此类似的Posted a more general question,以免混淆答案和讨论。
发布于 2010-11-19 09:01:39
你已经得到了正确的方法,但似乎有点迷失了它是如何正确的。
考虑一下你(正确地)说不能工作的代码:
DBHandle GetDB()
{
using( var db = DatabaseObj.GetHandle() )
{
db.Open();
return db;
}
}这段代码相当于:
DBHandle GetDB()
{
var db = DatabaseObj.GetHandle();
try
{
db.Open();
return db;
}
finally
{
if(db != null)//not included if db is a value-type
((IDisposable)db).Dispose();
}
}这里要注意的几件事包括,try直到赋值之后才会发生( using也是如此-它不会让您在using中的赋值之前避免异常),db被强制转换为IDisposable,这意味着如果赋值无效,它将无法编译,而且Dispose()可以隐式或显式实现,这将以任何一种方式工作。
当然,现在无论是否发生异常,finally块都将执行。您不能使用using,因为它等同于finally,并且如果发生异常,您只想在方法中使用Dispose() 。因此,你可以把finally转换成一个catch:
DBHandle GetDB()
{
var db = DatabaseObj.GetHandle();
try
{
db.Open();
return db;
}
catch
{
if(db != null)
((IDisposable)db).Dispose();
throw;
}
}这与您使用的几乎相同,只是添加了一个空检查(也许您可以排除它的需要),并且我使用的是纯throw (当您要重新抛出一个异常而不修改或检查它时,这通常是一个好主意。在某些情况下,抛出新的异常更好,在这种情况下,您应该包括原始异常作为新异常的InnerException属性,以便为调试人员提供进一步的信息)。
所以总而言之,你是在正确的轨道上。希望我已经帮你解释了原因。
发布于 2012-08-07 15:54:40
提示:当从using块返回一个可释放对象时,请记住在执行语句时完成对Dispose()的调用!
这样,从块中返回的对象在从函数中传出时就已经被释放了。
有关示例,请参阅以下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class MyDisposable : IDisposable
{
public void DoSomething()
{
Console.WriteLine(" In DoSomething");
}
#region IDisposable Members
public void Dispose()
{
Console.WriteLine(" In Dispose");
}
#endregion
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting Main\n");
Console.WriteLine("Before NormalMethod");
NormalMethod();
Console.WriteLine("After NormalMethod\n");
Console.WriteLine("Before ReturningMethod");
MyDisposable m = ReturningMethod();
m.DoSomething(); // Here the object already has been disposed!
Console.WriteLine("After ReturningMethod\n");
}
private static void NormalMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
Console.WriteLine(" In NormalMethod");
}
return;
}
private static MyDisposable ReturningMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
Console.WriteLine(" In ReturningMethod");
return myDisposable;
}
}
}
}这将产生以下输出:

发布于 2010-11-19 06:06:26
“using”就是为你做你的try/catch工作,只要有db.Open就行了;using将保证无论它是否抛出,它都会处理你的连接。
https://stackoverflow.com/questions/4220039
复制相似问题