使用中的产量回报

Jad*_*ias 17 .net c# using exception yield-return

如果我没记错的话,当我在using SqlConnection块内使用yield 时,我得到了运行时异常.

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();
}
Run Code Online (Sandbox Code Playgroud)

当我用yieldList 替换这些问题时,我每次迭代都添加了项目.

在内部using StreamReader块时,我没有发生同样的问题

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

有没有解释为什么例外事件发生在前一种情况而不是后者?这个建筑是否可取?

编辑为了得到我过去做的错误(早期处理)你应该调用下面的第一个方法:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用其他延迟执行的方法可以实现相同的错误,例如 System.Linq.Enumerable.Select()

Jam*_*rgy 5

请参阅这篇文章,using了解和问题的详细解释yield。因为您返回枚举器,所以 using 块在访问任何内容之前就已经销毁了上下文。答案有很好的解决方案,基本上,要么使包装器方法成为枚举器,要么构建一个列表。

using此外,将读者放在周围(而不是连接)通常更实用,并CommandBehavior.CloseConnection用于确保读者完成后释放资源。尽管这在您的情况下并不重要,但如果您从方法返回数据读取器,这将确保在处理读取器时正确关闭连接。

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

  • 在这种情况下,我会将“using”应用于 Reader 和 Connection。 (3认同)