我写的是:
using System;using System.Linq;
static class MyExtensions
{
public static IEnumerable<T> Inspect<T> (this IEnumerable<T> source)
{
Console.WriteLine ("In Inspect");
//return source; //Works, but does nothing
foreach(T item in source){
Console.WriteLine(item);
yield return item;
}
}
}
然后用这个来测试它:
var collection = Enumerable.Range(-5, 11)
.Select(x => new { Original = x, Square = x * x })
.Inspect()
.OrderBy(x => x.Square)
//.Inspect()
.ThenBy(x => x.Original)
;
foreach (var element in collection)
{
Console.WriteLine(element);
}
第一次使用Inspect()
效果很好。第二个已注释掉,无法编译。 OrderBy
的返回是 IOrderedEnumerable
。我本以为 IOrderedEnumerable
is-a IEnumerable
但是,我尝试了:
public static IOrderedEnumerable<T> Inspect<T> (this IOrderedEnumerable<T> source)
{
Console.WriteLine ("In Inspect (ordered)");
foreach(T item in source){
Console.WriteLine(item);
yield return item;
}
}
但这也不会编译。我被告知我不能有迭代器 block ,因为 System.Linq.IOrderedEnumberable 不是迭代器接口(interface)类型。
我错过了什么?我不明白为什么人们不想像处理原始集合一样迭代有序集合。
(使用 Mono 2.10.8.1(实际上是 C# 4.0)和 MonoDevelop 2.8.6.3)
更新:
正如 joshgo 善意指出的那样,我可以采用 IOrderedEnumerable
的输入参数,它确实充当 as-a IEnumerable
。但要进行迭代,我必须返回 IEnumerable,而我最初的错误是由 ThenBy
引起的,它坚持要给出 IOrderedEnumerable
。也很合理。但是这里有没有办法满足ThenBy
呢?
更新2:
在使用了两个答案中的代码之后(这两个答案都非常有帮助),我终于明白了为什么我不能将yield与IOrderedEnumerable返回一起使用:没有意义,因为这些值必须完全可用才能按顺序进行排序。因此,我也可以使用一个循环来打印所有项目,然后在最后返回一次源代码,而不是使用包含yield的循环。
最佳答案
我相信可以在这里找到错误的解释:Some help understanding "yield"
引用 Lasse V. Karlsen 的话:
A method using yield return must be declared as returning one of the following two interfaces: IEnumerable or IEnumerator
问题似乎与 yield
运算符和第二个函数 IOrderedEnumerable
的返回类型有关。
如果将返回类型从 IOrderedEnumerable
更改为 IEnumerable
,则第二次 Inspect() 调用将不再出错。但是,ThenBy()
调用现在将引发错误。如果您暂时将其注释掉,它会编译,但您确实无法访问 ThenBy()
方法。
var collection = Enumerable.Range(-5, 11)
.Select(x => new { Original = x, Square = x * x })
.Inspect()
.OrderBy(x => x.Square)
.Inspect()
//.ThenBy(x => x.Original)
;
foreach (var element in collection)
{
Console.WriteLine(element);
}
...
public static IEnumerable<T> Inspect<T> (this IOrderedEnumerable<T> source)
{
Console.WriteLine ("In Inspect (ordered)");
foreach(T item in source){
Console.WriteLine(item);
yield return item;
}
}
关于c# - 为什么不能将迭代器 block 与 IOrderedEnumerable 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12926313/