产量回报内使用 [英] Yield return inside usings

查看:156
本文介绍了产量回报内使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我记得正确的是,当我使用S $ C连接块中的收益率时,我得到运行时异常。

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

SqlDataReader reader = command.ExecuteReader();

//访问数据前调用读取。
while(reader.Read())
{
yield reader [0];
}

//完成阅读后调用关闭。
reader.Close();
}

当我更换 yield 在列表中,我每次迭代添加项目。



使用StreamReader时,我也没有遇到同样的问题使用(var streamReader = new StreamReader(fileName))
{
$ b $ $ b字符串;
while((line = streamReader.ReadLine())!= null)
{
yield return line;
}
}

是否有任何解释为什么例外在前一种情况下发生而不是在后者?这个建筑是否可行?



编辑要获得以前做过的错误(早期处理),您应该调用以下第一种方法:

  IEnumerable< string> read(string fileName)
{
using(var streamReader = new StreamReader(fileName))
{
return Read(streamReader);
} // Dispose将在ReadLine()之前执行,因为deffered执行
}

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

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

解决方案

请参阅此信息,以获得良好的解释使用收益的问题。因为你返回枚举器,所以使用块在任何东西被访问之前都已经破坏了上下文。答案有很好的解决方案,基本上,使包装方法是一个枚举器,或者建立一个列表。



另外通常更实用的是在阅读器周围使用而不是连接,并使用 CommandBehavior.CloseConnection 来确保读者完成时释放资源。虽然在您的情况下并不重要,但如果您从方法返回数据读取器,这将确保读者处理时连接被正确关闭。

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


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.

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;
    }
}

The same error can be achieved with other ways of deferring execution, such as System.Linq.Enumerable.Select()

解决方案

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.

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];
        }
   }

这篇关于产量回报内使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆