LINQ 标准的查询操作符 复合的 from 子句

复合的  from 子句

 

如果需要根据对象的一个成员进行过滤,而该成员本身是一个集合,就可以使用复合的 from 子句。

Racer 类定义了一个属性 Cars, Cars  是一个字符串数组。

要过滤驾驶 Ferrari  的所有冠军, 可以使用如下所示的 LINQ 查询。

第一个 from  子句访问从 Formyla1.GetChampions()返回的Racer  对象,

第二个 from  子句访问 Racer 类的属性 Cars,返回所有的string  类型的赛车。

接着在 Where  子句中使用这些赛车过滤驾驶 Ferrari 的所有车手

并使用LastName升序

 

private static void CompoundFrom()
        {
            var fd = from r in Formula1.GetChampions()
                     from c in r.Cars
                     where c == "Ferrari"
                     orderby r.LastName
                     select r.FirstName + " " + r.LastName;

            foreach (var racer in fd)
            {
                Console.WriteLine(racer);
            }
        }
结果把Cas中带有Ferrari 的9个车手名字列了出来:

image

C#编译器把复合的 from 子句和 LINQ  查询转换为 SelectMany()扩展方法。SelectMany()可用于迭代集合
中的集合。示例中 SelectMany()方法的重载版本如下所示:

public static IEnumerable < TResult > SelectMany < TSource, TCollection, TResult > (

this IEnumerable < TSource > source,
Func < TSource, IEnumerable < TCollection > > collectionSelector,
Func < TSource, TCollection, TResult > resultSelector);

下面的程序就是调用这个扩展方法,说明如下:
1.第一个参数是隐式参数,从 GetChampions()方法中接收 Racer 对象序列。

2.第二个参数(r => r.Cars)是 collectionSelector 委托,它定义了内部集合。在λ表达式r=>r.Cars  中,应返回赛车集合。r 本身是R集合,用这个又得到了Cars集合

3.第三个参数是一个委托,现在为每个赛车调用该委托,接收 Racer 和 Car 对象。

4.λ表达式创建了一个匿名类型,它带 Racer1  和 Car1  属性。匿名对象的 Racer1属性附上了r,Car1属性附上了c,属性名随意定的

5.这个SelectMany()方法的结果是摊平了赛手和赛车的层次结构,

5.为每辆赛车返回匿名类型的一个新对象集合。

这个新集合传送给Where()方法,过滤出驾驶 Ferrari  的赛手。最后,调用OrderBy()和Select()方法:

 

/// <summary>
        /// 复合的from子句
        /// </summary>
        private static void CompoundFrom()
        {
            var fd = Formula1.GetChampions().
                SelectMany( r => r.Cars, (r, c) => new { Racer1 = r, Car1 = c }).
                  Where(r => r.Car1 == "Ferrari").
                  OrderBy(r => r.Racer1.LastName).
                  Select(r => r.Racer1.FirstName + " " + r.Racer1.LastName);
            foreach (var racer in fd)
            {
                Console.WriteLine(racer);
            }


        }

 

结果和上面一样

把 SelectMany()泛型方法解析为这里使用的类型,所解析的类型如下所示。

在这个例子中,数据源是 Racer 类型,所过滤的集合是一个string  数组,当然所返回的匿名类型的名称是未知的,

这里显示为 TResult:

public static IEnumerable < TResult > SelectMany < Racer, string, TResult > (
this IEnumerable < Racer > source,   //Formula1.GetChampions()的结果
Func < Racer, IEnumerable < string > > collectionSelector,  // SelectMany( r => r.Cars,中的 r => r.Cars, 返回结果集为 IEnumerable < string >
Func < Racer, string, TResult > resultSelector);  //(r, c) => new { Racer1 = r, Car1 = c }).   // r, c, => new {} 返回结果为
TResult 到r 表达式左式的第一个参数r

查询仅从 LINQ 查询转换为扩展方法,所以结果与前面的相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值