查询与它生成的结果不同。
内存中集合包含对象的序列。
XElement>。
对于此源序列,查询可能会执行三种操作之一:
-
查询然后可能以各种方式对返回的序列进行排序或分组,如下面的示例所示(假定
scores是int[]):
IEnumerable<int> highScoresQuery = from score in scores where score > 80 orderby score descending select score;
- 请注意
highScoresQuery的新类型。
IEnumerable<string> highScoresQuery2 = from score in scores where score > 80 orderby score descending select $"The score is {score}";
-
检索有关源数据的单独值,如:
-
与特定条件匹配的元素数。
-
具有最大或最小值的元素。
-
例如,下面的查询从
scores整数数组返回大于 80 的分数的数量:
int highScoreCount = (from score in scores where score > 80 select score) .Count();
这种方法更具可读性,因为它使存储查询的变量与存储结果的查询分开。
IEnumerable<int> highScoresQuery3 = from score in scores where score > 80 select score; int scoreCount = highScoresQuery3.Count();
在上面的示例中,查询在 Count 调用中执行,因为 Count 必须循环访问结果才能确定 highScoresQuery 返回的元素数。
join 或 group 子句的结果可以充当相同查询表达式中的其他查询子句的源。查询变量
更具体地说,查询变量始终是可枚举类型,在 foreach 语句或对其 IEnumerator.MoveNext 方法的直接调用中循环访问时会生成元素序列。
该查询以 select 子句结尾。
static void Main() { // 数据源 int[] scores = { 90, 71, 82, 93, 75, 82 }; // 查询表达式 IEnumerable<int> scoreQuery = // 查询变量 from score in scores // 必须 where score > 80 // 可选 orderby score descending // 可选 select score; // 必须以 select 或者 group 结尾 // 执行查询并产生结果 foreach (int testScore in scoreQuery) { Console.WriteLine(testScore); } } // 输出: 93 90 82 82
只要既没有修改它,也没有修改数据源,便会生成相同结果。
在以下示例中,queryMajorCities 和 queryMajorCities2 都是查询变量:
var cities = new City { new city(){Name = "上海",Population = 24180000}, new city(){Name = "南京",Population = 8436200}, new city(){Name = "北京",Population = 21710000}, new city(){Name = "广州",Population = 14900000} }; // 查询语法 IEnumerable<City> queryMajorCities = from city in cities where city.Population > 100000 select city; // 基于方法的语法 IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > 100000);
它们不是查询变量,因为它们存储结果:
int highestScore = (from score in scores select score) .Max(); // 或者拆分表达式 IEnumerable<int> scoreQuery = from score in scores select score; int highScore = scoreQuery.Max(); // 下面的表达式返回相同的结果 int highScore = scores.Max(); List<City> largeCitiesList = (from country in countries from city in country.Cities where city.Population > 10000 select city) .ToList(); // 或者拆分表达式 IEnumerable<City> largeCitiesQuery = from country in countries from city in country.Cities where city.Population > 10000 select city; List<City> largeCitiesList2 = largeCitiesQuery.ToList();
有关表示查询的不同方式的详细信息,请参阅 LINQ 中的查询语法和方法语法。
查询变量的显式和隐式类型化
例如,本主题中前面演示的查询示例也可以使用隐式类型化进行表示:
// 在这里和所有查询中使用var都是可选的。querycities是一个IEnumerable<city>就像它是显式类型一样 var queryCities = from city in cities where city.Population > 100000 select city;
有关详细信息,请参阅隐式类型化局部变量和 LINQ 查询操作中的类型关系。
开始查询表达式
因为范围变量是强类型,所以可以使用点运算符访问该类型的任何可用成员。
IEnumerable<Country> countryAreaQuery =
from country in countries
where country.Area > 500000 //面积大于500000
select country;
范围变量一直处于范围中,直到查询使用分号或 continuation 子句退出。
若要查询每个 Country 中的 City 对象,请使用两个 from 子句,如下所示:
IEnumerable<City> cityQuery =
from country in countries
from city in country.Cities
where city.Population > 10000
select city;
from 子句。
结束查询表达式
查询表达式必须以 group 子句或 select 子句结尾。
group 子句
例如,下面的查询会创建包含一个或多个 Country 对象并且其键是 char 值的组的序列。
var queryCountryGroups = from country in countries group country by country.Name[0];
有关分组的详细信息,请参阅 group 子句。
select 子句
orderby 子句只按新顺序对元素进行排序,而 select 子句生成重新排序的 Country 对象的序列。
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
请注意,新对象使用对象初始值设定项进行初始化。
// 此处 var 是必须的,因为查询返回了匿名类型 var queryNameAndPop = from country in countries select new { Name = country.Name, Pop = country.Population };
有关可以使用 select 子句转换源数据的所有方法的详细信息,请参阅 select 子句。
使用“into”进行延续
若要执行这些附加操作,需要由 countryGroup 表示的延续。
// 该查询返回的类型是 IEnumerable<IGrouping<int, Country>> var percentileQuery = from country in countries let percentile = (int) country.Population / 10_000_000 group country by percentile into countryGroup where countryGroup.Key >= 20 orderby countryGroup.Key select countryGroup; // 分组是 IGrouping<int, Country> foreach (var grouping in percentileQuery) { Console.WriteLine(grouping.Key); foreach (var country in grouping) Console.WriteLine(country.Name + ":" + country.Population); }
有关详细信息,请参阅 into。
筛选、排序和联接
任何可选子句都可以在查询正文中使用零次或多次。
IEnumerable<City> queryCityPop =
from city in cities
where city.Population < 200000 && city.Population > 100000
select city;
有关详细信息,请参阅 where 子句。
orderby 子句
然后使用 Population 属性执行次要排序。
IEnumerable<Country> querySortedCountries =
from country in countries
orderby country.Area, country.Population descending
select country;
orderby 子句。
join 子句
筛选出其 Category 不与 categories 中的任何字符串匹配的产品。select 语句会投影其属性取自 cat 和 prod 的新类型。
var categoryQuery = from cat in categories join prod in products on cat equals prod.Category select new { Category = cat, Name = prod.Name };
join 子句。
let 子句
在下面的示例中,范围变量 firstName 存储 Split 返回的字符串数组的第一个元素。
string[] names = { "Svetlana Omelchenko", "Claire O'Donnell", "Sven Mortensen", "Cesar Garcia" }; IEnumerable<string> queryFirstNames = from name in names let firstName = name.Split(' ')[0] select firstName; foreach (string s in queryFirstNames)
Console.Write(s + " ");
//输出: Svetlana Claire Sven Cesar
有关详细信息,请参阅 let 子句。
查询表达式中的子查询
例如,下面的查询演示在 select 语句用于检索分组操作结果的查询表达式。
var queryGroupMax = from student in students group student by student.GradeLevel into studentGroup select new { Level = studentGroup.Key, HighestScore = (from student2 in studentGroup select student2.Scores.Average()) .Max() };
有关详细信息,请参阅如何:对分组操作执行子查询。
其他技术请参阅