Linq 如何在 IOrderedEnumerable 方法之后使用 IEnumerable 方法?

发布于 2024-08-07 18:58:54 字数 805 浏览 8 评论 0原文

在 Linq 中,Where 等扩展方法返回 IEnumerable 集合,但 OrderBy 等排序方法返回 IOrderedEnumerable 集合。

因此,如果您有一个以 OrderBy 结尾的查询(即返回 IOrderedEnumerable),则以后无法附加 Where 方法 -编译器抱怨类型被传递到 Where

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id);

query = query.Where(p => p.ProcessName.Length < 5);

但是,如果您在一个查询中完成所有操作,那就没问题了!

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id)
            .Where(p => p.ProcessName.Length < 5);

我查看了 Reflector 中的程序集,看看编译器是否对任何操作进行了重新排序,但似乎没有。这是如何运作的?

In Linq, extension methods like Where return an IEnumerable collection, but sorting methods like OrderBy return an IOrderedEnumerable collection.

So, if you have a query that ends with OrderBy (i.e. returns an IOrderedEnumerable), you can't later append a Where method - the compiler complains about the type being passed into Where.

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id);

query = query.Where(p => p.ProcessName.Length < 5);

However, if you do it all in one query, it's fine!

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id)
            .Where(p => p.ProcessName.Length < 5);

I've looked at the assembly in Reflector to see if the compiler was re-ordering any of the operations, but it doesn't seem to have. How does this work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

腹黑女流氓 2024-08-14 18:58:54

IOrderedEnumerable 扩展了 IEnumerable,因此您仍然可以使用任何扩展方法。您的第一个代码块不起作用的原因是您有效地编写了:

IOrderedEnumerable<Process> query = Process.GetProcesses()
                                           .Where(p => p.ProcessName.Length < 10)
                                           .OrderBy(p => p.Id);

// Fail: can't assign an IEnumerable<Process> into a variable 
// of type IOrderedEnumerable<Process>
query = query.Where(p => p.ProcessName.Length < 5);

失败是因为 query.Where(...) 仅返回 IEnumerable ,不能分配给 query 变量。问题不在于调用 Where - 而是将结果分配回原始变量。为了证明这一点,此代码可以正常工作:

var query = Process.GetProcesses()
                   .Where(p => p.ProcessName.Length < 10)
                   .OrderBy(p => p.Id);

// Introduce a new variable instead of trying to reuse the previous one
var query2 = query.Where(p => p.ProcessName.Length < 5);

或者,您可以将查询声明为 IEnumerable 来开始:

IEnumerable<Process> query = Process.GetProcesses()
                                    .Where(p => p.ProcessName.Length < 10)
                                    .OrderBy(p => p.Id);

// Fine
query = query.Where(p => p.ProcessName.Length < 5);

IOrderedEnumerable<T> extends IEnumerable<T> so you can still use any of the extension methods. The reason your first block of code didn't work is because you had effectively written:

IOrderedEnumerable<Process> query = Process.GetProcesses()
                                           .Where(p => p.ProcessName.Length < 10)
                                           .OrderBy(p => p.Id);

// Fail: can't assign an IEnumerable<Process> into a variable 
// of type IOrderedEnumerable<Process>
query = query.Where(p => p.ProcessName.Length < 5);

That fails because query.Where(...) only returns an IEnumerable<Process>, which can't be assigned to the query variable. It's not calling Where that's the problem - it's assigning the result back to the original variable. To demonstrate that, this code will work just fine:

var query = Process.GetProcesses()
                   .Where(p => p.ProcessName.Length < 10)
                   .OrderBy(p => p.Id);

// Introduce a new variable instead of trying to reuse the previous one
var query2 = query.Where(p => p.ProcessName.Length < 5);

Alternatively, you can declare query to be IEnumerable<T> to start with:

IEnumerable<Process> query = Process.GetProcesses()
                                    .Where(p => p.ProcessName.Length < 10)
                                    .OrderBy(p => p.Id);

// Fine
query = query.Where(p => p.ProcessName.Length < 5);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文