收益率返回与返回 IEnumerable

2023-12-30

我注意到阅读时有一些好奇的事情IDataReader在我无法理解的 using 语句中。虽然我确信答案很简单。

为什么在里面时using (SqlDataReader rd) { ... }如果我直接执行yield return阅读器在阅读期间保持打开状态。但如果我直接执行return调用 SqlDataReader 扩展方法(如下所述),读取器在可枚举可实现之前关闭?

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

    rd.NextResult();
}

为了完全清楚我的要求,我不确定为什么以下内容有根本不同:

根据 @TimSchmelter 的要求,一个充实的示例:

/*
 * 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
}

Summary:该方法的两个版本defer, 但是因为ReadSomeProcExt不推迟执行,在执行传递回调用者之前(即之前Enumerate<T>能跑)。ReadSomeProc另一方面,在将读取器传递回调用者之前不会创建读取器,因此在读取所有值之前不会释放容器。

当你的方法使用yield return,编译器实际上更改了编译后的代码以返回IEnumerable<>, and 方法中的代码将不会运行,直到其他代码开始迭代返回的IEnumerable<>.

这意味着下面的代码甚至不会运行您的第一行Enumerate方法,然后再处理读取器并返回值。当其他人开始迭代你返回的值时IEnumerable<>,读者已经处理完毕。

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

但是这段代码会执行整个Enumerate()方法以产生List<>返回前的结果:

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

另一方面,无论是谁calling具有此代码的方法在计算结果之前实际上并不执行该方法:

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

但是当他们执行返回的那一刻IEnumerable<>, the using块打开了,但没有打开Dispose()直到IEnumerable<>完成迭代,此时您已经从数据读取器读取了所需的所有内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

收益率返回与返回 IEnumerable 的相关文章

随机推荐

  • Android 任务管理器或系统对话框

    我想知道有没有一种方法可以在显示系统对话框时获取事件 例如任务管理器 关闭警报 我可以通过如下意图从我的活动中关闭系统对话框 Intent closeDialog new Intent Intent ACTION CLOSE SYSTEM
  • 如何查找一个方法中调用的所有方法?

    如何在特定方法中调用其他类的方法 EXAMPLE 方法 getItem1 public String getItem1 throws UnsupportedEncodingException String a 2 a getBytes a
  • 去掉chart js折线图中的竖线

    I am using Chart js to generate maps and have customised it to a good extent But I am not able to remove the vertical gr
  • 鼠标悬停在 html 上更改图像

    我试图让图像在鼠标悬停时发生变化 这段代码适用于 IE 但不适用于其他浏览器 如 chrome opera safari 等 有什么想法吗 a href img src img login button 11 jpg a 您应该使用 ID
  • JavaScript 触发 InputEvent.isTrusted = true

    我正在尝试自动化一些任务JavaScript我需要使用InputEvent 但是当我使用正常事件时 我得到事件 isTrusted false而我的活动什么也没做 这是我的事件代码 var event new InputEvent inpu
  • JavaScript:通过类方法创建和销毁类实例

    我试图弄清楚如何通过类方法删除对象 我希望能够创建一个具有从内存中释放对象的 destroy 方法的类 到目前为止 我所做的研究还没有结论 我知道垃圾收集最终会处理该对象 但我想要一种更明确的方法来销毁它 这可能吗 class constr
  • 如何返回满足特定事件序列的行?

    我正在尝试提取满足特定事件序列的 UserID 的记录 如果用户有一个 JOIN 然后是一个后续的 CANCEL 然后是一个后续的 JOIN 我想在结果集中返回它们 我需要根据需要一次运行此查询一天 或一次运行几天 下表显示了满足和不满足该
  • 如何使用scanf限制输入长度

    在此程序中 我采用了大小为 3 4 的维字符数组 只要我每行输入 3 个字符 它就可以正常工作 例如 如果我输入abc abd abd我得到相同的输出 但如果我在第一行 第二行或第三行输入更多字母 则会出现错误 我应该如何检查二维中的空字符
  • 如何防止NFC标签克隆?

    我正在使用 NFC 标签制作一个应用程序 并且必须防止 NFC 标签被克隆 我见过许多其他 NFC 标签 当尝试克隆时 会显示弹出消息 克隆受到限制 标签由密钥保护 我希望我的 NFC 标签具有相同的安全性 这取决于您使用的标签类型以及您想
  • NSOpenPanel runModal 崩溃?

    我有一个基于此论坛上找到的代码的例程 FSRef useOpenFileToGetFSRef NSString fileName requiredFileType NSString requiredFileType FSRef fileFS
  • 轴标签与表达式的 R 对齐

    我想绘制一个变量名称及其符号 由于某些变量的名称很长 因此我尝试将换行符与轴标签混合使用 这会导致对齐中发生有趣的事情 par mar c 1 12 1 1 plot y 1 6 1 6 yaxt n ylim c 1 6 ylab axi
  • 从面板中删除关键侦听器

    是否可以清除我放在我的监听器JPanel 当我调用一个方法时 我放了一个KeyListener在面板上 但是当我退出此方法时 我想清除该侦听器 这是我的方法 private void stopBall final Graphics2D g2
  • VScode 抱怨 Java 项目没有显式编码集

    直到最近我一直使用 vscode 没有任何问题 现在没有错误出现 一些变量永远不会改变颜色 我不断收到错误消息 项目 没有明确的编码集 我不知道我需要做什么来修复它 就在几分钟前 我也遇到了同样的问题 这是我修复它的方法 单击齿轮图标 单击
  • 更新 cabal-install,但版本没有改变

    目前我正在使用 cabal install 1 16 0 我尝试更新 cabal install 因为有人告诉我有更新版本的 ghc 7 6 1 可用 除了这条消息之外 安装结果非常成功 警告 无法在 Users MyName Librar
  • 对 flatList 中的项目进行排序

    在我的 React Native 应用程序中 我显示了我的办公室提供的服务以及这些服务在平面列表中的位置 我还在同一个公寓列表中显示了从该人当前地址开始的服务里程 我希望这些服务按里程排序 下面是我的屏幕数据 以下地点提供服务 123 Te
  • 将 ftable(列联表)转换为 R 中的数据帧

    我正在生成一个ftable 通过在xtabs命令的结果上运行ftable 并且我得到以下内容 Var1 Var2 date group 2007 01 01 q1 1 9 q2 2 8
  • @jsonview of jackson 不使用 jax-rs

    我写了以下代码 class A public static class Public Entity class public class B JsonView A Public class int a int b public class
  • 如何强制关闭串口连接?

    我有通过 USB 串行通信连接到 PC 的设备 我正在执行以下步骤 启动设备 开机 设备将在我的 PC 中检测为 COMx 名称 开始我的申请 基于COM PID VID 我连接到设备 进行沟通 到目前为止我没有遇到任何问题 当我关闭设备时
  • 接口的扩展方法的优先级是否低于不太具体的扩展方法?

    我有以下扩展类 public static class MatcherExtensions public static ExecMatcher
  • 收益率返回与返回 IEnumerable

    我注意到阅读时有一些好奇的事情IDataReader在我无法理解的 using 语句中 虽然我确信答案很简单 为什么在里面时using SqlDataReader rd 如果我直接执行yield return阅读器在阅读期间保持打开状态 但