返回一个 Disposable 对象以在 using 块中使用
如何在函数中返回一次性对象以确保它在 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() ){ /* ... */ }
编辑: 发布了一个与此类似的更普遍的问题,以免混淆答案和讨论。
How do I return a disposable object in my function to ensure that it works properly within a using
block? In my function, I want to act on the disposable object and also account for errors, which complicates this.
I have something similar to the following code so far:
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() ){ /* ... */ }
Edit: Posted a more general question similar to this so as to not confuse answers and discussion.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
提示:当从使用块返回一次性对象时,请记住
在执行 return 语句时完成对 Dispose() 的调用!!!
因此,从 using 块内返回的对象在从函数中出来时将已经被释放。
请参阅以下代码示例
这将产生以下输出:
Hint: When returning a disposable object from your using-block, have in mind that
the call to Dispose() is done when the return-statement is executed!!!
So an object returned from within a using-block will already be disposed when it comes out of the function.
See the following code for an example
This will produce the following output:
你的方法是正确的,但似乎有点不知道如何才是正确的。
考虑一下您(正确地)说无法工作的代码:
此代码几乎相当于:
这里需要注意的一些事情包括,直到分配之后才会发生尝试(对于
using 也是如此
- 它不会让您在using
中的赋值之前避免异常,并且db
被强制转换为IDisposable
含义如果该赋值无效,则无法编译,而且Dispose()
可以隐式或显式实现,并且无论哪种方式都可以工作。当然,无论是否发生异常,
finally
块都会执行。您不能使用using
,因为它相当于finally
并且您希望仅在方法中使用Dispose()
> 如果发生异常。因此,你采用了finally并将其变成了一个catch:这与你所拥有的几乎相同,除了添加了一个空检查(也许你可以排除对它的需要)并且我正在使用裸< code>throw (当您要在不更改或检查异常的情况下重新抛出异常时,这通常是一个好主意。在某些情况下,抛出新的异常更好,在这种情况下,您应该将原始异常包含为 <该新异常的 code>InnerException 属性,以便为调试人员提供进一步的信息)。
总而言之,您走在正确的道路上。希望我能帮助解释原因。
You've got the right approach, but seem a bit lost as to how it's right.
Consider the code that you (correctly) say can't work:
This code is pretty much equivalent to:
A few things of note here include that the try doesn't happen until after the assignment (the same is true of
using
- it doesn't save you from exceptions prior to the assignment in theusing
) and thatdb
is cast toIDisposable
meaning both that it can't compile if that assignment isn't valid, and also thatDispose()
can be either implicitly or explicitly implemented and this will work either way.Now of course,
finally
blocks will execute whether an exception occurs or not. You can't useusing
because it's equivalent to afinally
and you want toDispose()
in your method only if an exception occurs. Hence you take the finally and turn it into a catch:This is pretty much the same as you have, except for the addition of a null check (maybe you can rule out the need for it) and that I'm using the bare
throw
(it's generally a good idea when you are going to re-throw an exception without altering or examining it. In some cases throwing a new exception is better, in which case you should include the original as theInnerException
property of that new exception, so as to provide further information to someone debugging).So all in all, you were on the right track. Hopefully I've helped explain why.
“使用”正在为你做你的 try/catch 工作,只需 db.Open; using 将保证无论它是否抛出,它都会释放你的连接。
'Using' is doing your try/catch work for you, just have the db.Open; using will guarantee that regardless of whether it throws, it will dispose your connection.
如果 DBHandle 实现了 IDisposable 那么你所拥有的应该可以工作。
没有返回 IDisposable 的“特殊”方式。
If DBHandle implements IDisposable then what you have should work.
There is no 'special' way of returning IDisposable.
返回值只需实现
IDisposable
。实际上,此语句必须为真:
如果可以编译,则可以将
GetDB()
放入using
语句中。The return value simply has to implement
IDisposable
.In practical terms, this statement must be true:
If that compiles, you can put
GetDB()
in ausing
statement.