gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 21:03:24 24 4
gpt4 key购买 nike

我是这样写的:

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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com