c# - 为什么不能将迭代器 block 与 IOrderedEnumerable 一起使用

标签 c# .net linq mono iterator

我写的是:

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/

相关文章:

c# - 如何使用 DataTable.Select() 选择 Null/空值?

c# - 我可以使用无限范围并对其进行操作吗?

c# - 在不使用 foreach 循环的 C# 中填充列表中的列表。更好的方法?

c# - 使用 Open XML SDK 替换 Word 文件中的书签文本

c# - 如何在给定类名的情况下获取用户定义的对象类型?

c# - ComboBox 强制崩溃(不是我的代码)

c# - EF6 LINQ 嵌套包括

c# - 创建包含空格(字符之间有一个空格)且第一个字符不是空格的随机字符串

.net - F# 适合物理应用吗?

C# Epplus - 如何对除第一行以外的所有数据进行排序