收益回报与收益IEnumerable

收益回报与收益IEnumerable

本文介绍了收益回报与收益IEnumerable T的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到我对无法理解的using语句中的 IDataReader 进行读取感到有些好奇。虽然我确信答案很简单。



为什么在内使用(SqlDataReader rd){...} 如果我直接执行收益率,则阅读器在读取期间保持打开状态。但是,如果我执行直接的 return 调用SqlDataReader扩展方法(如下所示),该方法在实现可枚举之前关闭了读者?

 公共静态IEnumerable< T>枚举< T>(此SqlDataReader rd)
{
而(rd.Read())
的收益率返回rd.ConvertTo< T>(); //扩展方法包装FastMember

rd.NextResult();
}

要绝对清楚我要问的是什么,我不确定为什么以下是根本不同的内容:

当您的方法使用 yield return 时,编译器实际上会更改已编译的返回 IEnumerable<> 的代码,并且在其他代码开始对返回的 IEnumerable<进行迭代之前,方法中的代码将不会运行。 > 。



这意味着下面的代码甚至没有运行 Enumerate 方法,然后将其分配给读取器并返回一个值。当其他人开始遍历您返回的 IEnumerable<> 时,阅读器已被处置。

  using(SqlDataReader rd = cmd.ExecuteReader()){
返回rd.Enumerate< T>();
}

但是此代码将执行整个 Enumerate() 方法,以便在返回之前生成结果 List<> :

  using(SqlDataReader rd = cmd.ExecuteReader()){
返回rd.Enumerate< T>()。ToList();
}

另一方面,谁叫呼叫方法使用此代码,直到对结果求值才真正执行该方法:

  using(SqlDataReader rd = cmd.ExecuteReader() ){
while(rd.Read())
收益回报率rd.ConvertTo< T>(); //扩展方法包装FastMember
}

但是当它们执行返回的 IEnumerable<> ,打开 using 块,而不显示 Dispose(),直到 IEnumerable<> 完成其迭代为止,此时您已经从数据读取器中读取了所需的所有内容。


I've noticed something curious about reading from an IDataReader within a using statement that I can't comprehend. Though I'm sure the answer is simple.

Why is it that whilst inside the using (SqlDataReader rd) { ... } if I directly perform a yield return the reader stays open for the duration of the read. But if I perform a direct return calling a SqlDataReader extension method (outlined below) that the reader closes before the enumerable can be actualized?

public static IEnumerable<T> Enumerate<T>(this SqlDataReader rd)
{
    while (rd.Read())
        yield return rd.ConvertTo<T>(); //extension method wrapping FastMember

    rd.NextResult();
}

To be absolutely clear of what I'm asking, I'm unsure why the following are fundamentally different:

/*
 * contrived methods
 */
public IEnumerable<T> ReadSomeProc<T>() {
    using (var db = new SqlConnection("connection string"))
    {
        var cmd = new SqlCommand("dbo.someProc", db);

        using(var rd = cmd.ExecuteReader())
        {
            while(rd.Read())
                yield return rd.ConvertTo<T>(); //extension method wrapping FastMember
        }
    }
}


//vs
public IEnumerable<T> ReadSomeProcExt<T>() {
    using (var db = new SqlConnection("connection string"))
    {
        var cmd = new SqlCommand("dbo.someProc", db);

        using(var rd = cmd.ExecuteReader())
        {
            return rd.Enumerate<T>(); //outlined above
        }
    }
}

/*
 * usage
 */
var lst = ReadSomeProc<SomeObect>();

foreach(var l in lst){
    //this works
}

//vs
var lst2 = ReadSomeProcExt<SomeObect>();

foreach(var l in list){
    //throws exception, invalid attempt to read when reader is closed
}
解决方案

When your method uses yield return, the compiler actually changes the compiled code to return an IEnumerable<>, and the code in your method will not run until other code starts iterating over the returned IEnumerable<>.

That means that the code below doesn't even run the first line of your Enumerate method before it disposes the reader and returns a value. By the time someone else starts iterating over your returned IEnumerable<>, the reader has already been disposed.

using(SqlDataReader rd = cmd.ExecuteReader()){
    return rd.Enumerate<T>();
}

But this code would execute the entire Enumerate() method in order to produce a List<> of results prior to returning:

using(SqlDataReader rd = cmd.ExecuteReader()){
    return rd.Enumerate<T>().ToList();
}

On the other hand, whoever's calling the method with this code doesn't actually execute the method until the result is evaluated:

using(SqlDataReader rd = cmd.ExecuteReader()){
    while(rd.Read())
        yield return rd.ConvertTo<T>(); //extension method wrapping FastMember
}

But the moment they execute the returned IEnumerable<>, the using block opens up, and it doesn't Dispose() until the IEnumerable<> finishes its iterations, at which point you will have already read everything you need from the data reader.

这篇关于收益回报与收益IEnumerable T的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 19:18