这是我的手译,保留你的范围变量和类型信息:
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);