如何编写代码:
var list = from uint x in M join uint y in N on x equals y into templist
from uint z in templist join uint t in R on z equals t select z;
就Join
或GroupJoin
方法而言?
根据MS Docs,将join
和into
的组合转换为对GroupJoin
的调用。我只想知道上面的代码如何调用GroupJoin
。
这是我的手动翻译,保留了范围变量和信息:
var list = M.GroupJoin(N, (uint x) => x, (uint y) => y, (uint x, IEnumerable<uint> templist) => templist)
.SelectMany(templist => templist.Join(R, z => z, t => t, (z, t) => z));
使用LINQPad,您可以在IQueryable
上进行查询并获得lambda翻译。
将此内容放入LINQPad:
var M = Enumerable.Empty<uint>().AsQueryable();
var N = Enumerable.Empty<uint>().AsQueryable();
var R = Enumerable.Empty<uint>().AsQueryable();
var list = from uint x in M
join uint y in N on x equals y into templist
from uint z in templist
join uint t in R on z equals t
select z;
list.Dump();
并且在lambda选项卡上将其取回:
System.Linq.EmptyPartition`1[System.UInt32]
.Cast ()
.GroupJoin (
System.Linq.EmptyPartition`1[System.UInt32]
.Cast (),
x => x,
y => y,
(x, templist) =>
new
{
x = x,
templist = templist
}
)
.SelectMany (
temp0 => temp0.templist.Cast (),
(temp0, z) =>
new
{
temp0 = temp0,
z = z
}
)
.Join (
System.Linq.EmptyPartition`1[System.UInt32]
.Cast (),
temp1 => temp1.z,
t => t,
(temp1, t) => temp1.z
)
因此,似乎编译器更喜欢转换为SelectMany
并链接Join
,而不是嵌套Join
。似乎编译器喜欢传递所有范围变量,而不是注意例如不再需要x
和temp0
,只需将z
传递到Join
。
我会使用我喜欢的范围变量命名来写我的原著,就像这样:
var list = M.GroupJoin(N, m => m, n => n, (m, nj) => nj)
.SelectMany(nj => nj.Join(R, n => n, r => r, (n, r) => n));
我将像这样模拟编译器的流畅链接:
var list = M.GroupJoin(N, m => n, n => n, (m, nj) => nj)
.SelectMany(nj => nj)
.Join(R, n => n, r => r, (n, r) => n);
最后,鉴于结果,没有理由使用GroupJoin
,所以我只需要这样做:
var list = from x in M
join y in N on x equals y
join t in R on y equals t
select y;
或使用lambda语法:
var list = M.Join(N, m => m, n => n, (m, n) => n)
.Join(R, n => n, r => r, (n, r) => n);