LINQ的基本语法包含如下的8个上下文关键字,这些关键字和具体的说明如下:
关键字 | 说明 |
from | 指定范围变量和数据源 |
where | 根据bool表达式从数据源中筛选数据 |
select | 指定查询结果中的元素所具有的类型或表现形式 |
group | 对查询结果按照键值进行分组(IGrouping<TKey,TElement>) |
into | 提供一个标识符,它可以充当对join、group或select子句结果的引用 |
orderby | 对查询出的元素进行排序(ascending/descending) |
join | 按照两个指定匹配条件来Equals连接两个数据源 |
let | 产生一个用于存储查询表达式中的子表达式查询结果的范围变量 |
1.from子句
class CompoundFrom
{
// The element type of the data source.
public class Student
{
public string LastName { get; set; }
public List<int> Scores {get; set;}
}
static void Main()
{
// 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 {LastName="Omelchenko", Scores= new List<int> {97, 72, 81, 60}},
new Student {LastName="O'Donnell", Scores= new List<int> {75, 84, 91, 39}},
new Student {LastName="Mortensen", Scores= new List<int> {88, 94, 65, 85}},
new Student {LastName="Garcia", Scores= new List<int> {97, 89, 85, 82}},
new Student {LastName="Beebe", Scores= new List<int> {35, 72, 91, 70}}
};
// Use a compound from to access the inner sequence within each element.
// Note the similarity to a nested foreach statement.
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
// Execute the queries.
Console.WriteLine("scoreQuery:");
// Rest the mouse pointer on scoreQuery in the following line to
// see its type. The type is IEnumerable<'a>, where 'a is an
// anonymous type defined as new {string Last, int score}. That is,
// each instance of this anonymous type has two members, a string
// (Last) and an int (score).
foreach (var student in scoreQuery)
{
Console.WriteLine("{0} Score: {1}", student.Last, student.score);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
*/
2.where子句
where子句用在查询表达式中,用于指定将在查询表达式中返回数据源中的哪些元素。 它将一个布尔条件(谓词)应用于每
个源元素(由范围变量引用),并返回满足指定条件的元素。 一个查询表达式可以包含多个 where子句,一个子句可以包含多
个谓词子表达式。
例:
where子句筛选出除小于五的数字外的所有数字。
class WhereSample
{
static void Main()
{
// Simple data source. Arrays support IEnumerable<T>.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
// Simple query with one predicate in where clause.
var queryLowNums =
from num in numbers
where num < 5
select num;
// Execute the query.
foreach (var s in queryLowNums)
{
Console.Write(s.ToString() + " ");
}
}
}
//Output: 4 1 3 2 0
注:where子句是一种筛选机制。 除了不能是第一个或最后一个子句外,它几乎可以放在查询表达式中的任何位置。
3.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
4.group子句
可以用group子句结束查询表达式
例:
// Query variable is an IEnumerable<IGrouping<char, Student>>
var studentQuery1 =
from student in students
group student by student.Last[0];
5.into子句
class IntoSample1
{
static void Main()
{
// Create a data source.
string[] words = { "apples", "blueberries", "oranges", "bananas", "apricots"};
// Create the query.
var wordGroups1 =
from w in words
group w by w[0] into fruitGroup
where fruitGroup.Count() >= 2
select new { FirstLetter = fruitGroup.Key, Words = fruitGroup.Count() };
// Execute the query. Note that we only iterate over the groups,
// not the items in each group
foreach (var item in wordGroups1)
{
Console.WriteLine(" {0} has {1} elements.", item.FirstLetter, item.Words);
}
// Keep the console window open in debug mode
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
a has 2 elements.
b has 2 elements.
*/
仅当希望对每个组执行附加查询操作时,才需在 group子句中使用 into。
6.orderby子句
例:第一个查询按字母顺序从 A 开始对字词排序,而第二个查询则按降序对相同的字词排序。
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
*/
7.join子句
join子句将 2 个源序列作为输入。 每个序列中的元素都必须是可以与其他序列中的相应属性进行比较的属性,
或者包含一个这样的属性。 join子句使用特殊 equals 关键字比较指定的键是否相等。 join子句执行的所有联接
都是同等联接。 join子句的输出形式取决于执行的联接的具体类型。 以下是 3 种最常见的联接类型:
内部联接
分组联接
左外部联接
内部联接
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { ProductName = prod.Name, Category = category.Name }; //produces flat sequence
分组联接
var innerGroupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new { CategoryName = category.Name, Products = prodGroup };
左外部联接
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product { Name = String.Empty, CategoryID = 0 })
select new { CatName = category.Name, ProdName = item.Name };
8.let子句
在查询表达式中,存储子表达式的结果有时很有帮助,可在后续子句中使用。 可以通过 let关键字执行此操作,
该关键字创建一个新的范围变量并通过提供的表达式结果初始化该变量。 使用值进行初始化后,范围变量不能
用于存储另一个值。 但是,如果范围变量持有可查询类型,则可以查询该变量。
以两种方式使用以下示例 let:
创建一个可以查询其自身的可枚举类型。
使查询仅调用一次范围变量 word上的 ToLower。 如果不使用 let,则不得不调用 where子句中的每个谓词的 ToLower。
class LetSample1
{
static void Main()
{
string[] strings =
{
"A penny saved is a penny earned.",
"The early bird catches the worm.",
"The pen is mightier than the sword."
};
// Split the sentence into an array of words
// and select those whose first letter is a vowel.
var earlyBirdQuery =
from sentence in strings
let words = sentence.Split(' ')
from word in words
let w = word.ToLower()
where w[0] == 'a' || w[0] == 'e'
|| w[0] == 'i' || w[0] == 'o'
|| w[0] == 'u'
select word;
// Execute the query.
foreach (var v in earlyBirdQuery)
{
Console.WriteLine("\"{0}\" starts with a vowel", v);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
"A" starts with a vowel
"is" starts with a vowel
"a" starts with a vowel
"earned." starts with a vowel
"early" starts with a vowel
"is" starts with a vowel
*/