目录
我遇到的问题:
_List = (from hero in _List orderby HaveColor(hero) descending select hero).ToList<int>();
基本 LINQ 查询操作
获取数据源
在 LINQ 查询中,第一步是指定数据源。 和大多数编程语言相同,在使用 C# 时也必须先声明变量,然后才能使用它。 在 LINQ 查询中,先使用 from
子句引入数据源 (customers
) 和 范围变量 (cust
)。
//queryAllCustomers is an IEnumerable<Customer>
var queryAllCustomers = from cust in customers select cust;
范围变量就像 foreach
循环中的迭代变量,但查询表达式中不会真正发生迭代。 当执行查询时,范围变量将充当对 customers
中每个连续的元素的引用。 由于编译器可以推断 cust
的类型,因此无需显式指定它。 可通过 let
子句引入其他范围变量。 有关详细信息,请参阅 let 子句。
筛选
或许,最常见的查询操作是以布尔表达式的形式应用筛选器。 筛选器使查询仅返回表达式为 true 的元素。 将通过使用 where
子句生成结果。 筛选器实际指定要从源序列排除哪些元素。 在下列示例中,仅返回地址位于“London”的 customers
。
var queryLondonCustomers = from cust in customers
where cust.City == "London"
select cust;
可使用熟悉的 C# 逻辑 AND
和 OR
运算符,在 where
子句中根据需要应用尽可能多的筛选器表达式。 例如,若要仅返回来自“London”的客户 AND
该客户名称为“Devon”,可编写以下代码:
where cust.City == "London" && cust.Name == "Devon"
要返回来自 London 或 Paris 的客户,可编写以下代码:
where cust.City == "London" || cust.City == "Paris"
中间件排序
对返回的数据进行 排序 通常很方便。 orderby
子句根据要排序类型的默认比较器,对返回序列中的元素排序。 例如,基于 Name
属性,可将下列查询扩展为对结果排序。 由于 Name
是字符串,默认比较器将按字母顺序从 A 到 Z 进行排序。
var queryLondonCustomers3 =
from cust in customers
where cust.City == "London"
orderby cust.Name ascending
select cust;
要对结果进行从 Z 到 A 的逆序排序,请使用 orderby…descending
子句。请参阅 orderby子句。
分组
group
子句用于对根据您指定的键所获得的结果进行分组。 例如,可指定按 City
对结果进行分组,使来自 London 或 Paris 的所有客户位于单独的组内。 在这种情况下,cust.City
是键。
// queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>>
var queryCustomersByCity =
from cust in customers
group cust by cust.City;
// customerGroup is an IGrouping<string, Customer>
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (Customer customer in customerGroup)
{
Console.WriteLine(" {0}", customer.Name);
}
}
使用 group
子句结束查询时,结果将以 列表 的形式列出。 列表中的每个元素都是具有 Key
成员的对象,列表中的元素根据该键被分组。 在循环访问生成组序列的查询时,必须使用嵌套 foreach
循环。 外层循环循环访问每个组,内层循环循环访问每个组的成员。
如果必须引用某个组操作的结果,可使用 into
关键字创建能被进一步查询的标识符。 下列查询仅返回包含两个以上客户的组:
// custQuery is an IEnumerable<IGrouping<string, Customer>>
var custQuery =
from cust in customers
group cust by cust.City into custGroup
where custGroup.Count() > 2
orderby custGroup.Key
select custGroup;
联接
联接操作在不同序列间创建关联,这些序列在数据源中未被显式模块化。 例如,可通过执行联接来查找所有位置相同的客户和分销商。 在 LINQ 中,join
子句始终作用于对象集合,而非直接作用于数据库表。
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
在 LINQ 中,不必像在 SQL 中那样频繁使用 join
,因为 LINQ 中的外键在对象模型中表示为包含项集合的属性。 例如 Customer
对象包含 Order
对象的集合。 不必执行联接,只需使用点表示法访问订单:
from order in Customer.Orders...
选择(投影)
select
子句生成查询结果并指定每个返回的元素的“形状”或类型。 例如,可以指定结果包含的是整个 Customer
对象、仅一个成员、成员的子集,还是某个基于计算或新对象创建的完全不同的结果类型。 当 select
子句生成除源元素副本以外的内容时,该操作称为投影。 使用投影转换数据是 LINQ 查询表达式的一种强大功能。
orderby 子句
在查询表达式中,orderby
子句可导致返回的序列或子序列(组)以 升序或降序排序 。 若要执行一个或多个次级排序操作,可以指定多个键。 元素类型的默认比较器执行排序。 默认排序顺序为升序。 还可以指定自定义比较器。 但是,只适用于使用基于方法的语法。
编译时,orderby
子句将转换为对 OrderBy 方法的调用。 orderby
子句中的多个关键值将转换为 ThenBy 方法调用。
在以下示例中,第一个查询按字母顺序从 A 开始对字词排序,而第二个查询则按降序对相同的字词排序。 (ascending
关键字是默认排序值,可省略。)
class OrderbySample1
{
static void Main()
{
// Create a delicious data source.
string[] fruits = { "cherry", "apple", "blueberry" };
// Query for ascending sort.
IEnumerable<string> sortAscendingQuery =
from fruit in fruits
orderby fruit //"ascending" is default
select fruit;
// Query for descending sort.
IEnumerable<string> sortDescendingQuery =
from w in fruits
orderby w descending
select w;
// Execute the query.
Console.WriteLine("Ascending:");
foreach (string s in sortAscendingQuery)
{
Console.WriteLine(s);
}
// Execute the query.
Console.WriteLine(Environment.NewLine + "Descending:");
foreach (string s in sortDescendingQuery)
{
Console.WriteLine(s);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Ascending:
apple
blueberry
cherry
Descending:
cherry
blueberry
apple
*/
以下示例对学生的姓氏进行主要排序,然后对其名字进行次要排序。
class OrderbySample2
{
// The element type of the data source.
public class Student
{
public string First { get; set; }
public string Last { get; set; }
public int ID { get; set; }
}
public static List<Student> GetStudents()
{
// Use a collection initializer to create the data source. Note that each element
// in the list contains an inner sequence of scores.
List<Student> students = new List<Student>
{
new Student {First="Svetlana", Last="Omelchenko", ID=111},
new Student {First="Claire", Last="O'Donnell", ID=112},
new Student {First="Sven", Last="Mortensen", ID=113},
new Student {First="Cesar", Last="Garcia", ID=114},
new Student {First="Debra", Last="Garcia", ID=115}
};
return students;
}
static void Main(string[] args)
{
// Create the data source.
List<Student> students = GetStudents();
// Create the query.
IEnumerable<Student> sortedStudents =
from student in students
orderby student.Last ascending, student.First ascending
select student;
// Execute the query.
Console.WriteLine("sortedStudents:");
foreach (Student student in sortedStudents)
Console.WriteLine(student.Last + " " + student.First);
// Now create groups and sort the groups. The query first sorts the names
// of all students so that they will be in alphabetical order after they are
// grouped. The second orderby sorts the group keys in alpha order.
var sortedGroups =
from student in students
orderby student.Last, student.First
group student by student.Last[0] into newGroup
orderby newGroup.Key
select newGroup;
// Execute the query.
Console.WriteLine(Environment.NewLine + "sortedGroups:");
foreach (var studentGroup in sortedGroups)
{
Console.WriteLine(studentGroup.Key);
foreach (var student in studentGroup)
{
Console.WriteLine(" {0}, {1}", student.Last, student.First);
}
}
// Keep the console window open in debug mode
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
sortedStudents:
Garcia Cesar
Garcia Debra
Mortensen Sven
O'Donnell Claire
Omelchenko Svetlana
sortedGroups:
G
Garcia, Cesar
Garcia, Debra
M
Mortensen, Sven
O
O'Donnell, Claire
Omelchenko, Svetlana
*/
select 子句
在查询表达式中,select
子句指定在执行查询时产生的 值的类型。 根据计算所有以前的子句以及根据 select
子句本身的所有表达式得出结果。 查询表达式 必须以 select
子句或 group 子句结尾。
以下示例演示查询表达式中的简单的 select
子句。
class SelectSample1
{
static void Main()
{
//Create the data source
List<int> Scores = new List<int>() { 97, 92, 81, 60 };
// Create the query.
IEnumerable<int> queryHighScores =
from score in Scores
where score > 80
select score;
// Execute the query.
foreach (int i in queryHighScores)
{
Console.Write(i + " ");
}
}
}
//Output: 97 92 81
select
子句生成的序列的类型确定查询变量 queryHighScores
的类型。 在最简单的情况下,select
子句仅指定范围变量。 这将导致返回的序列包含与数据源类型相同的元素。 但是,select
子句还提供了强大的机制,用于将源数据转换(或投影)为新类型。