下面是一个示例代码,用于使用我在谷歌搜索时在一些地方找到的yield关键字从数据库检索数据:

public IEnumerable<object> ExecuteSelect(string commandText)
{
    using (IDbConnection connection = CreateConnection())
    {
        using (IDbCommand cmd = CreateCommand(commandText, connection))
        {
             connection.Open();
             using (IDbDataReader reader = cmd.ExecuteReader())
             {
                while(reader.Read())
                {
                    yield return reader["SomeField"];
                }
             }
             connection.Close();
        }
    }
}

我是否正确地认为,在这个示例代码中,如果我们不迭代整个 datareader ,连接就不会关闭?

如果我正确理解产量,这是一个不会关闭连接的示例。

foreach(object obj in ExecuteSelect(commandText))
{
  break;
}

对于可能不是灾难性的数据库连接,我认为 GC 最终会清理它,但如果它不是连接而是更关键的资源怎么办?

有帮助吗?

解决方案

编译器合成的 Iterator 实现了 IDisposable,当退出 foreach 循环时 foreach 会调用它。

Iterator 的 Dispose() 方法将在提前退出时清除 using 语句。

只要您在 foreach 循环、using() 块中使用迭代器,或以其他方式调用 Dispose() 方法,就会发生迭代器的清理。

其他提示

连接将自动关闭,因为您在“using”块内使用它。

从我尝试过的简单测试来看,aku 是正确的,一旦 foreach 块退出,就会调用 dispose。

@大卫 :然而,调用堆栈在调用之间保留,因此连接不会关闭,因为在下一次调用时,我们将返回到yield之后的下一条指令,即while块。

我的理解是,当迭代器被释放时,连接也会随之被释放。我还认为不需要 Connection.Close,因为当由于 using 子句而处置对象时,它将被处理。

这是一个我试图测试其行为的简单程序......

class Program
{
    static void Main(string[] args)
    {
        foreach (int v in getValues())
        {
            Console.WriteLine(v);
        }
        Console.ReadKey();

        foreach (int v in getValues())
        {
            Console.WriteLine(v);
            break;
        }
        Console.ReadKey();
    }

    public static IEnumerable<int> getValues()
    {
        using (TestDisposable t = new TestDisposable())
        {
            for(int i = 0; i<10; i++)
                yield return t.GetValue();
        }
    }
}

public class TestDisposable : IDisposable
{
    private int value;

    public void Dispose()
    {
        Console.WriteLine("Disposed");
    }

    public int GetValue()
    {
        value += 1;
        return value;
    }
}

判断从 这个技术解释, ,您的代码将不会按预期工作,但会在第二项上中止,因为返回第一项时连接已经关闭。

@乔尔·高夫罗:是的,我应该继续读下去。 第三部分 本系列的解释了编译器为finally块添加了特殊处理,以便仅在 真实的 结尾。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top