LINQ(转换操作符)

前面提到,查询可以推迟到访问数据项时再执行。在迭代使用查询时,查询会执行。而使用转换操作符会立即执行查询,把查询结果放在数组、列表或字典中。

在下面的例子中,调用ToList()扩展方法,立即执行查询,得到的结果放在List类中:

        static void ToList()
        {
            List racers = (from r in Formula1.GetChampions()
                       where r.Starts > 100
                       orderby r.Starts descending
                       select r).ToList();
            foreach(var racer in racers)
            {
                System.Console.WriteLine($"{racer.ToString()} {racer:S}");
            }
        }

查询结果显示如下:

Graham Hill 176
Jack Brabham 125
Denny Hulme 112
John Surtees 111

把返回的对象放在列表中并没有这么简单。例如,对于集合类从赛车到赛车手的快速访问,可以使用新类Lookup

注:Dictionary类只支持一个键对应一个值。在System.Linq名称空间的类Lookup类中,一个键而可以对应多个值。

使用复合的from查询,可以摊平赛车手和赛车序列,创建带有Car和Racer属性的匿名类型。在返回的Lookup对象中,键的类型应是表示汽车的string,值的类型应是Racer。为了进行这个选择,可以给ToLookup()方法的一个重载版本传递一个键和一个元素选择器。键选择器引用Car属性,元素选择器引用Racer属性:

        static void ToLookup()
        {
            var racers = (from r in Formula1.GetChampions()
                       from c in r.Cars
                       select new {
                           Car = c,
                           Racer = r
                       }).ToLookup(rc=>rc.Car,rc=>rc.Racer);
            if(racers.Contains("Ferrari"))
            {
                foreach(var ferrariRacer in racers["Ferrari"])
                {
                    System.Console.WriteLine(ferrariRacer.ToString());
                }
            }
        }

用Lookup类的索引器访问的所有"Ferrari"冠军,结果如下:

Alberto Ascari
Juan Manuel Fangio
Mike Hawthorn
Phil Hill
John Surtees

如果需要在非类型化的集合上(如ArrayList)使用LINQ查询,就可以使用Cast()方法。在下面的例子中,基于Object类型的ArrayList集合用Race对象填充。为定义强类型化的查询,可使用Cast()方法:

        static void ConvertWithCast()
        {
            var list = new ArrayList(Formula1.GetChampions() as ICollection);
            var query = from r in list.Cast()
                      where r.Country == "Italy"
                      orderby r.Wins descending
                      select r;
            foreach(var racer in query)
            {
                System.Console.WriteLine($"{racer:A}");
            }
        }

结果仅包含来自意大利的一级方程式冠军:

Alberto,Ascari,Italy; starts:32, wins:10
Nino,Farina,Italy; starts:33, wins:5

 

你可能感兴趣的:(LINQ,C#)