首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >返回在using块中使用的Disposable对象

返回在using块中使用的Disposable对象
EN

Stack Overflow用户
提问于 2010-11-19 06:02:03
回答 5查看 6.9K关注 0票数 3

如何在我的函数中返回一个可丢弃的对象,以确保它在using块中正常工作?在我的函数中,我希望对可丢弃的对象执行操作,并考虑错误,这会使问题复杂化。

到目前为止,我的代码类似于以下代码:

代码语言:javascript
复制
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,以免混淆答案和讨论。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-11-19 09:01:39

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

考虑一下你(正确地)说不能工作的代码:

代码语言:javascript
复制
DBHandle GetDB()
{
    using( var db = DatabaseObj.GetHandle() )
    {
        db.Open();
        return db;
    }
}

这段代码相当于:

代码语言:javascript
复制
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:

代码语言:javascript
复制
DBHandle GetDB()
{
    var db = DatabaseObj.GetHandle();
    try
    {
      db.Open();
      return db;
    }
    catch
    {
        if(db != null)
          ((IDisposable)db).Dispose();
        throw;
    }
}

这与您使用的几乎相同,只是添加了一个空检查(也许您可以排除它的需要),并且我使用的是纯throw (当您要重新抛出一个异常而不修改或检查它时,这通常是一个好主意。在某些情况下,抛出新的异常更好,在这种情况下,您应该包括原始异常作为新异常的InnerException属性,以便为调试人员提供进一步的信息)。

所以总而言之,你是在正确的轨道上。希望我已经帮你解释了原因。

票数 2
EN

Stack Overflow用户

发布于 2012-08-07 15:54:40

提示:当从using块返回一个可释放对象时,请记住在执行语句时完成对Dispose()的调用!

这样,从块中返回的对象在从函数中传出时就已经被释放了。

有关示例,请参阅以下代码

代码语言:javascript
复制
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;
            }
        }
    }
}

这将产生以下输出:

票数 8
EN

Stack Overflow用户

发布于 2010-11-19 06:06:26

“using”就是为你做你的try/catch工作,只要有db.Open就行了;using将保证无论它是否抛出,它都会处理你的连接。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4220039

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档