join + into子句如何转换为GroupJoin

问题描述 投票:1回答:1

如何编写代码:

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;

JoinGroupJoin方法而言?

根据MS Docs,将joininto的组合转换为对GroupJoin的调用。我只想知道上面的代码如何调用GroupJoin

c# linq join
1个回答
1
投票

这是我的手动翻译,保留了范围变量和信息:

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。似乎编译器喜欢传递所有范围变量,而不是注意例如不再需要xtemp0,只需将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);
© www.soinside.com 2019 - 2024. All rights reserved.