using 语句中的成员范围

Scope of members inside using statement

我对以下代码和 using 语句的范围及其对象处理感到困惑。

using(DbFactory db = new DbFactory())
{
   Repository repo = new Repository<someobject>(db);
   result = repo.Get(somecondition);
}

在这段代码中,执行 using 块后会发生什么 DbFactory 会被处置?
using 语句中使用的 repo 变量的范围是什么?
DbFactoryRepository 使用,它有一个成员变量将保存 DbFactory。 那么这会保留 DbFactory 的处理吗?

编辑1:

Repository repo;
ResultObject result;
using(DbFactory db = new DbFactory())
{
   repo = new Repository<someobject>(db);
   result = repo.Get(somecondition);
}

public class Repository
{
    private _dbFactory;

    public Repository(DbFactory dbFactory)
    {
        _dbFactory = dbFactory;
    }
}

现在 DbFactory 会在 using 语句后被释放吗?

will the DbFactory gets disposed?

是的。

What will be the scope of repo variable used inside the using statement?

repo的范围是它所在的块,所以它包裹的那对花括号('{','}')。在这种情况下,它恰好重合在您的 using 声明正文中,是的。

repo 变量的范围(在您的第一种情况下)是 using 语句。您不能在 using 语句之外引用它,因为它已在其中声明。

我们无法判断 result 变量的范围,因为您没有显示它的声明,但它至少是 "bigger than the using statement".

更有趣的是result的值所指的对象在DbFactory被释放后的可用性如何。那是 implementation-specific,基本上......我希望如果访问任何 result 属性需要进一步的数据库查询(例如获取外键引用的对象)那么它会失败,但是任何已经获取的东西应该没问题。

至于销毁的时间——DbFactory 将在 using 语句结束时销毁。这与垃圾收集完全分开,并且 Repository 对象可能仍然有对它的引用——但在工厂被处理后它可能就没用了。因此,如果您在 using 语句后调用 repo.Get(...) ,您可能会看到一个异常,这取决于该代码实际对工厂做了什么,以及如何处置工厂的行为。同样,处置不是垃圾收集。它只是调用 Dispose 方法 - CLR 不会以任何特殊方式关心它。

如果回购也是一次性的,您可能也想处理它,例如:

using(DbFactory db = new DbFactory())
using(Repository repo = new Repository<someobject>(db))
{
   result = repo.Get(somecondition);
}

这个:

Repository repo;
ResultObject result;
using(DbFactory db = new DbFactory())
{
   repo = new Repository<someobject>(db);
   result = repo.Get(somecondition);
}

与这个相同:

Repository repo;
ResultObject result;
{
    DbFactory db = new DbFactory()
    repo = new Repository<someobject>(db);
    result = repo.Get(somecondition);
    db.Dispose();
}

因此,尽管 db 对象本身不会消失(对它的引用将保留在 Repository 实例中,但它将处于 Disposed/Closed 状态。取决于 DbFactory 的实现,这可能会破坏您的代码。

您没有提供完整的代码以及它应该做什么,但我认为您应该朝这个方向前进:

  1. 在您的 Repository 对象中实现 IDisposable,并在其中处理 DbFactory:

    public class Repository : IDisposable
    {
        private _dbFactory;
    
        public Repository(DbFactory dbFactory)
        {
            _dbFactory = dbFactory;
        }
    
        public void Dispose()
        {
            _dbFactory.Dispose();
        }
    } 
    
  2. 现在这样使用:

    ResultObject result;
    using (Repository repo = new Repository(new DbFactory())
    {
        result = repo.Get(somecondition);
    }
    

或嵌套使用:

using (DbFactory db = new DbFactory())
{
    using(Repository repo = new Repository(db))
    {
        result = repo.Get(somecondition);
    }
}