为什么使用yield关键字时,我只能使用普通的IEnumerable?
鉴于此代码:
IEnumerable<object> FilteredList()
{
foreach( object item in FullList )
{
if( IsItemInPartialList( item ) )
yield return item;
}
}
为什么我不应该这样编码?:
IEnumerable<object> FilteredList()
{
var list = new List<object>();
foreach( object item in FullList )
{
if( IsItemInPartialList( item ) )
list.Add(item);
}
return list;
}
我有点理解yield
关键字的作用。 它告诉编译器构建某种类型的东西(一个迭代器)。 但为什么使用它? 除了少一点代码之外,它对我有什么作用?
使用yield
会使收藏懒惰。
假设你只需要前五项。 按照你的方式,我必须遍历整个列表以获得前五项。 有了yield
,我只能循环前五项。
迭代器块的好处是它们懒惰地工作。 所以你可以写这样的过滤方法:
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, bool> predicate)
{
foreach (var item in source)
{
if (predicate(item))
{
yield return item;
}
}
}
这将允许你只要你喜欢就过滤一个流,从不缓冲多于一个单一的项目。 例如,如果您只需要返回序列中的第一个值,那么您为什么要将所有内容都复制到新列表中?
作为另一个例子,您可以使用迭代器块轻松创建无限流。 例如,下面是一系列随机数字:
public static IEnumerable<int> RandomSequence(int minInclusive, int maxExclusive)
{
Random rng = new Random();
while (true)
{
yield return rng.Next(minInclusive, maxExclusive);
}
}
你将如何在列表中存储无限序列?
我的Edulinq博客系列给出了大量使用迭代器块的LINQ to Objects的示例实现。 LINQ从根本上来说是懒惰的 - 把事情放在一个列表中根本不会那样工作。
使用“列表”代码,您必须先处理完整列表,然后才能将其传递到下一步。 “yield”版本立即将处理后的项目传递给下一步。 如果该“下一步”包含“.Take(10)”,那么“收益”版本将只处理前10个项目并忘记其余的项目。 “列表”代码将处理所有内容。
这意味着当您需要进行大量处理和/或需要处理大量项目列表时,您会发现最大的不同。
链接地址: http://www.djcxy.com/p/9101.html上一篇: Why use the yield keyword, when I could just use an ordinary IEnumerable?