返回一次性对象用在使用块 [英] Return a Disposable object for use in a using block

查看:152
本文介绍了返回一次性对象用在使用块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何我在函数返回的一次性对象,以确保其正常工作中的使用阻止?在我的功能,我想采取行动的支配对象上也占了错误,复杂化这

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() ){ /* ... */ }

编辑:的发布一个更普遍的问题与此类似,因此不会混淆的回答和讨论。

Posted a more general question similar to this so as to not confuse answers and discussion.

推荐答案

您已经得到了正确的方法,但似乎有点失去了它是如何是正确的。

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:

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();
    }
}

请注意的几件事包括在这里的尝试没有按'T发生,直到分配后(同样是使用真正 - 它不从异常使用<在转让之前救你/ code>)和分贝被转换为的IDisposable 既意味着它不能如果编译转让是无效的,而且也是的Dispose()可以明确或含蓄地实施,这将工作无论哪种方式。

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 the using) and that db is cast to IDisposable meaning both that it can't compile if that assignment isn't valid, and also that Dispose() can be either implicitly or explicitly implemented and this will work either way.

现在当然,最后块将执行是否发生异常。不能使用使用,因为它是相当于最后,你想的Dispose( )在方法的如果出现异常。因此,你把最后并把它变成一个问题:

Now of course, finally blocks will execute whether an exception occurs or not. You can't use using because it's equivalent to a finally and you want to Dispose() in your method only if an exception occurs. Hence you take the finally and turn it into a catch:

DBHandle GetDB()
{
    var db = DatabaseObj.GetHandle();
    try
    {
      db.Open();
      return db;
    }
    catch
    {
        if(db != null)
          ((IDisposable)db).Dispose();
        throw;
    }
}

这是相当多的,你有一样的,除了为增加了一个空检查的(也许可以排除它的需要)和我使用的裸罚球(它通常是一个好主意,你什么时候重新抛出异常而不改变或研究它。在某些情况下,抛出一个新的异常是更好的,在这种情况下,你应该包括原作为新的的InnerException 属性例外,这样才能提供进一步的信息给别人调试)。

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 the InnerException 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.

这篇关于返回一次性对象用在使用块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆