- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我注意到在我无法理解的 using 语句中从 IDataReader
读取时有些奇怪。虽然我确信答案很简单。
为什么在 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();
}
为了完全清楚我在问什么,我不确定为什么以下内容根本不同:
A fleshed out example, as per @TimSchmelter's request:
/*
* 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: Both versions of the method defer, but because
ReadSomeProcExt
doesn't defer execution, the reader is disposed before execution is passed back to the caller (i.e. beforeEnumerate<T>
can run).ReadSomeProc
, on the other hand, doesn't create the reader until it's been passed back to the caller, so it doesn't dispose the container until all its values have been read.
当您的方法使用 yield return
时,编译器实际上更改了编译后的代码以返回 IEnumerable<>
, 并且 在其他代码开始迭代返回的 IEnumerable<>
之前,您的方法中的代码不会运行.
这意味着下面的代码甚至不会运行您的 Enumerate
的第一行在处理读取器并返回值之前的方法。当其他人开始迭代您返回的 IEnumerable<>
时,读者已经被处置。
using(SqlDataReader rd = cmd.ExecuteReader()){
return rd.Enumerate<T>();
}
但这段代码会执行整个 Enumerate()
方法以产生List<>
返回前的结果:
using(SqlDataReader rd = cmd.ExecuteReader()){
return rd.Enumerate<T>().ToList();
}
另一方面,无论谁使用这段代码调用方法,在计算结果之前都不会真正执行该方法:
using(SqlDataReader rd = cmd.ExecuteReader()){
while(rd.Read())
yield return rd.ConvertTo<T>(); //extension method wrapping FastMember
}
但是当他们执行返回的 IEnumerable<>
时, using
block 打开了,但它没有 Dispose()
直到 IEnumerable<>
完成它的迭代,此时您已经从数据读取器读取了您需要的所有内容。
关于c# - yield 返回与返回 IEnumerable<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45695872/
任何人都可以向我解释 IEnumerable 和 IEnumerator 之间的区别是什么, 以及如何使用它们? 谢谢!!! 最佳答案 通常,一个 IEnumerable是可以枚举的对象,例如列表或数
function TSomething.Concat(const E: IEnumerable>): IEnumerable; begin Result := TConcatIterator.Cr
我正试图找到解决这个问题的办法: 给定一个 IEnumerable> 我需要一个返回输入的方法/算法,但是如果多个 IEnumerable 具有相同的元素,则每个巧合/组只返回一个。 例如 I
我有一个有趣的问题:给定一个 IEnumerable , 是否有可能产生 IEnumerable> 的序列一次将相同的相邻字符串分组? 让我解释一下。 1。基本说明示例: 考虑以下 IEnumerab
我有课 public class Test { public void M1(IEnumerable> p) { } public void M2(IEnumerable)> p) {
我尝试解决下一个练习: 输入:整数列表 count >= 1;一些正整数 k 输出:此整数的所有可能元组,长度为 k ; 例如 输入: {1, 2}; k = 4 输出: { {1, 1, 1, 1
抱歉奇怪的标题。我想要实现的目标很简单: IEnumerable> listoflist; IEnumerable combined = listoflist.CombineStuff(); 例子:
公共(public)类项目 { ... public class Order { public List Items ... } public class Customer {
我有一个 IEnumerable>我想转换为单一维度集合的集合。是否可以使用通用扩展方法来实现这一点?现在我正在这样做以实现它。 List filteredCombinations = new Lis
我有一个 IEnumerable> CustomObject在哪里有一个 x (用作键(在本例中为 1 、 2 、 3 ))和 y值(value)。一些假数据: { { {1, 2}, {2, 4
我需要做的是选择嵌套元素列表,这是我的查询 returns IEnumerable>这是我的 linq 表达式: from a in (questions.Select(x => x.AnswerLi
如何使用 LINQ(或其他方式)将 IEnumerables 的 IEnumerable 拆分为一个平面 IEnumerable? 最佳答案 enumerable.SelectMany(x => x)
例如: public interface IEnumerable { IEnumerator GetEnumerator(); } //This interface allows the c
我对 Reflection.Emit 有疑问。我想要动态创建的类,它具有 ICollection 的简单实现。我定义的所有方法都很好,而不是接下来的两个: public IEnumerator Get
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Why was IEnumerable made covariant in C# 4? 我正在查看 MSDN
IEnumerator.MoveNext() 的实现是否预计会相对较快?或者如果“移动到下一项” 包括磁盘 IO、Web 请求或其他可能长时间运行的操作是否可以? 例如,我正在处理一个处理文档的项目,
以下代码创建了 List 的中间实例并在 yield 返回之前将值附加到它。有没有一种好的方法可以避免创建实例并直接 yield 返回单元格值? IEnumerable> GetStrValues()
我有两个 IEnumerable 对象,我想验证其中一个是否包含另一个的所有元素。 我正在使用 obj1.Intersect(obj2).Any() 但交集没有像我预期的那样工作。即使 obj2 中只
我正在尝试这个 MSDN page 上的例子.我试图更改 GetEnumerator 方法。我知道那似乎有些不对劲,但它符合要求然后就不会运行。错误是枚举器尚未启动,应该调用 MoveNext,但 它
我写过关于自定义 IEnumerator 的文章。从中生成 IEnumerable 的最简单方法是什么?理想的解决方案(一行代码)是是否有一些用于该目的的类。还是我必须自己创建? 最佳答案 不幸的是,
我是一名优秀的程序员,十分优秀!