里面usings产量收益收益、产量、里面、usings

2023-09-03 12:09:09 作者:杨家千金

如果我没有记错,当我用使用的SqlConnection 块内部收益率我得到了运行时异常。

If I recall correctly that when I used yield inside using SqlConnection blocks I got runtime exceptions.

using (var connection = new SqlConnection(connectionString))
{
    var command = new SqlCommand(queryString, connection);
    connection.Open();

    SqlDataReader reader = command.ExecuteReader();

    // Call Read before accessing data.
    while (reader.Read())
    {
        yield reader[0];
    }

    // Call Close when done reading.
    reader.Close();
}

这些问题解决了,当我更换收益率通过在那里我添加的项目列表中的每个迭代。

Those problems were solved when I replaced yield by a List where I added items each iteration.

使用的StreamReader 块同样的问题并没有发生在我身上时,里面的

The same problem didn't happen yet to me when inside using StreamReader blocks

using (var streamReader = new StreamReader(fileName))
{
    string line;
    while ((line = streamReader.ReadLine()) != null)
    {
        yield return line;
    }
}

有没有异常的原因发生在前者的情况下,而不是在后面的任何解释?这是建设建议?

Is there any explanation why Exceptions happened in the former case and not in the latter? Is this construction advisable?

修改要获得我过去做了错误(早处置),你应该叫下面的第一种方法:

EDIT To get the error (early disposal) that I did in the past you should call the first method below:

IEnumerable<string> Read(string fileName)
{
    using (var streamReader = new StreamReader(fileName))
    {
        return Read(streamReader);
    } // Dispose will be executed before ReadLine() because of deffered execution
}

IEnumerable<string> Read(StreamReader streamReader)
{
    string line;
    while ((line = streamReader.ReadLine()) != null)
    {
        yield return line;
    }
}

可以延期执行的其他方法,比如可以达到相同的误差 System.Linq.Enumerable.Select()

推荐答案

请参阅this帖子对问题使用收益率一个很好的解释与。因为你在枚举返回,使用块将已经被破坏的背景下任何访问之前。这些问题的答案具有良好的解决方案,基本上,要么使包装方法的枚举,或建立一个列表,而不是。

See this post for a good explanation of the issues with using and yield. Because you return in enumerator, the using block will already have destroyed the context before anything is accessed. The answers have good solutions, basically, either make the wrapper method an enumerator, or build a list instead.

此外,它通常是更实际有使用周围的读者,而不是连接,并使用 CommandBehavior.CloseConnection 以确保当读者进行资源被释放。虽然它并没有真正的问题在您的情况,如果你曾经从一个方法返回一个数据读取器,这将确保连接正常时,读写器配置被关闭。

Also it's usually more practical to have using around the reader, not the connection, and use CommandBehavior.CloseConnection to ensure resources are released when the reader's done. Though it doesn't really matter in your situation, if you ever return a data reader from a method, this will ensure the connection is closed properly when the reader is disposed.

   using(SqlDataReader reader = 
             command.ExecuteReader(CommandBehavior.CloseConnection)) {
        while (reader.Read())
        {
            yield reader[0];
        }
   }