Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么Queryable.SelectMany(…)重载接受Func<;S、 IEnumerable<;R>&燃气轮机;而不是Func<;S、 IQueryable<;R>>;?_C#_Linq_Ienumerable_Iqueryable - Fatal编程技术网

C# 为什么Queryable.SelectMany(…)重载接受Func<;S、 IEnumerable<;R>&燃气轮机;而不是Func<;S、 IQueryable<;R>>;?

C# 为什么Queryable.SelectMany(…)重载接受Func<;S、 IEnumerable<;R>&燃气轮机;而不是Func<;S、 IQueryable<;R>>;?,c#,linq,ienumerable,iqueryable,C#,Linq,Ienumerable,Iqueryable,考虑以下功能: IQueryable<Bar> foo(IEnumerable<IQueryable<Bar>> sources) { return from source in sources.AsQueryable() from bar in source where bar.Xzy == 123 select bar; } IQueryable foo(IEnumerable源代码

考虑以下功能:

IQueryable<Bar> foo(IEnumerable<IQueryable<Bar>> sources)
{
    return
        from source in sources.AsQueryable()
        from bar in source
        where bar.Xzy == 123
        select bar;
}
IQueryable foo(IEnumerable源代码)
{
返回
来自sources.AsQueryable()中的source
源代码中的自条
其中bar.Xzy==123
选择栏;
}
直觉上,我希望它在每个源的上下文中执行“from…where…select”表达式。但是,我相信它只会对源代码执行“from bar in…”部分,而将“where…select”部分作为LINQ to Objects查询执行。最终的结果是,SomeTable的所有行都将从每个源中检索,而不仅仅是那些匹配“where”条件的行


乍一看,我猜想这是因为调用SelectMany会导致“source”表达式隐式转换为IEnumerable。我不确定实现是什么样子的,但是它接受Func,这样where…select表达式就被传递给IQueryable提供程序,这难道没有意义吗?

我认为这取决于编译器如何解释您的查询。它实际上将查询转化为如下内容(严格的从左到右解析):

至关重要的是,您的过滤器首先对枚举每个源的结果进行操作

还要注意,
AsQueryable()
实际上是多余的,因为它并没有使您的源变得比原来更可查询,而是使源的枚举变得可查询,而且您也不是在查询该集合,而是在查询单个源

你真正想要的是这样的,我想:

sources.SelectMany(source => source.Where(bar => bar.Xzy == 123))
这改变了对条款相对“优先顺序”的解释

实际上,我不确定您将如何使用LINQ语法设计后者

更新:事实上,这里有一个方法:

from source in sources
let qsource = (from bar in source
               where bar.Xzy == 123
               select bar)
from result in qsource
select result

出于这个原因,我通常倾向于使用扩展方法手工创建非平凡的查询。

源代码的类型是什么。SomeTable?如果将
foo
的返回类型更改为
IQueryable
,会发生什么情况?@Lee,对不起,我认为SomeTable属性在示例中没有意义。我将“source.SomeTable”改为“source”。我认为将返回类型更改为IQueryable不会改变查询的行为。返回类型应该有所不同,因为
IEnumerable
重载返回
IEnumerable
,而
IQueryable
重载返回
IQueryable
。因此,如果返回类型更改为
IQueryable
,并且选择了
SelectMany
IEnumerable
重载,则函数将无法编译。@Lee,我不太明白你的意思。“IEnumerable重载”指的是什么?我认为该方法中的查询表达式的类型是IQueryable,它也实现了IEnumerable,因此我不确定为什么它很重要,除非foo的调用方将返回值传递给其他LINQ方法。接受IEnumerable作为选择器是一个设计决策。你只是在问为什么做出这个决定吗?谢谢,我最后使用了一个LINQ表达式,就像你更新的答案一样。我只是想弄明白为什么最初的查询没有达到我的预期。我最初在我的“real”查询中添加了AsQueryable()调用,它认为通过强制使用Queryable.SelectMany而不是Enumerable.SelectMany可以解决我的问题(它没有)。
from source in sources
let qsource = (from bar in source
               where bar.Xzy == 123
               select bar)
from result in qsource
select result