# 查询表达式基础(C# 编程指南)
## 什么是查询?它有什么用途?
“查询”是指一组指令,这些指令描述要从一个或多个给定数据源检索的数据以及返回的数据应该使用的格式和组织形式。查询不同于它所产生的结果。
通常,源数据会在逻辑上组织为相同种类的元素序列。SQL 数据库表包含一个行序列。与此类似,ADO.NET [DataTable](https://msdn.microsoft.com/zh-cn/library/system.data.datatable.aspx) 包含一个 [DataRow](https://msdn.microsoft.com/zh-cn/library/system.data.datarow.aspx) 对象序列。在 XML 文件中,有一个 XML 元素“序列”(不过这些元素按分层形式组织为树结构)。内存中的集合包含一个对象序列。
从应用程序的角度来看,原始源数据的具体类型和结构并不重要。应用程序始终将源数据视为一个 [IEnumerable<T>](https://msdn.microsoft.com/zh-cn/library/9eekhta0.aspx) 或 [IQueryable<T>](https://msdn.microsoft.com/zh-cn/library/bb351562.aspx) 集合。在 LINQ to XML 中,源数据显示为一个 **IEnumerable**<[XElement](https://msdn.microsoft.com/zh-cn/library/system.xml.linq.xelement.aspx)>。在 LINQ to DataSet 中,它是一个 **IEnumerable**<[DataRow](https://msdn.microsoft.com/zh-cn/library/system.data.datarow.aspx)>。在 LINQ to SQL 中,它是您定义用来表示 SQL 表中数据的任何自定义对象的 **IEnumerable** 或 **IQueryable**。
指定此源序列后,查询可以进行下列三项工作之一:
* 检索一个元素子集以产生一个新序列,但不修改单个元素。然后,查询可以按各种方式对返回的序列进行排序或分组,如下面的示例所示(假定 scores 是 **int[]**):
```
IEnumerable<int> highScoresQuery =
from score in scores
where score > 80
orderby score descending
select score;
```
* 如上一个示例所述检索一个元素序列,但是将这些元素转换为具有新类型的对象。例如,查询可以只从数据源中的某些客户记录检索姓氏。或者,查询可以检索完整的记录,再使用它构建另一个内存中对象类型甚至 XML 数据,然后生成最终的结果序列。下面的示例演示了从 **int** 到 **string** 的转换。请注意 highScoresQuery 的新类型。
```
IEnumerable<string> highScoresQuery2 =
from score in scores
where score > 80
orderby score descending
select String.Format("The score is {0}", score);
```
* 检索有关源数据的单一值,例如:
* 符合某个条件的元素的数量。
* 具有最大值或最小值的元素。
* 符合某个条件的第一个元素,或一组指定元素中的特定值之和。例如,下面的查询从 scores 整数数组中返回高于 80 的分数的数量。
```
int highScoreCount =
(from score in scores
where score > 80
select score)
.Count();
```
在上一个示例中,请注意在 **Count** 方法调用之前的查询表达式两旁使用了括号。另一种表示方式是使用一个新变量来存储具体结果。此技术的可读性更好,因为它将存储查询的变量与存储结果的查询区分开来。
```
IEnumerable<int> highScoresQuery3 =
from score in scores
where score > 80
select score;
int scoreCount = highScoresQuery3.Count();
```
在上一个示例中,查询是在 **Count** 调用中执行的,因为 **Count** 必须循环访问结果以便确定 highScoresQuery 返回的元素数量。
## 什么是查询表达式?
“查询表达式”是用查询语法表示的查询,是一流的语言构造。它就像任何其他表达式一样,并且可以用在 C# 表达式有效的任何上下文中。查询表达式由一组用类似于 SQL 或 XQuery 的声明性语法编写的子句组成。每个子句又包含一个或多个 C# 表达式,而这些表达式本身又可能是查询表达式或包含查询表达式。
查询表达式必须以 [from](https://msdn.microsoft.com/zh-cn/library/bb383978.aspx) 子句开头,并且必须以 [select](https://msdn.microsoft.com/zh-cn/library/bb384087.aspx) 或 [group](https://msdn.microsoft.com/zh-cn/library/bb384063.aspx) 子句结尾。在第一个 **from** 子句和最后一个 **select** 或 **group** 子句之间,查询表达式可以包含一个或多个下列可选子句:[where](https://msdn.microsoft.com/zh-cn/library/bb311043.aspx)、[orderby](https://msdn.microsoft.com/zh-cn/library/bb383982.aspx)、[join](https://msdn.microsoft.com/zh-cn/library/bb311040.aspx)、[let](https://msdn.microsoft.com/zh-cn/library/bb383976.aspx) 甚至附加的 [from](https://msdn.microsoft.com/zh-cn/library/bb383978.aspx) 子句。还可以使用 [into](https://msdn.microsoft.com/zh-cn/library/bb311045.aspx) 关键字使 **join** 或 **group** 子句的结果能够充当同一查询表达式中附加查询子句的源。
### 查询变量
在 LINQ 中,查询变量是任何存储查询(而非查询结果)的变量。更具体地说,查询变量始终是一个可枚举的类型,当在 **foreach** 语句中或在对其 **IEnumerator.MoveNext** 方法的直接调用中循环访问它时,它会生成一序列元素。
下面的代码示例演示了一个简单的查询表达式,它含有一个数据源、一个筛选子句和一个排序子句,但不对源元素进行转换。 **select** 子句结束了该查询。
```
static void Main()
{
// Data source.
int[] scores = { 90, 71, 82, 93, 75, 82 };
// Query Expression.
IEnumerable<int> scoreQuery = //query variable
from score in scores //required
where score > 80 // optional
orderby score descending // optional
select score; //must end with select or group
// Execute the query to produce the results
foreach (int testScore in scoreQuery)
{
Console.WriteLine(testScore);
}
}
// Outputs: 93 90 82 82
```
在上一个示例中,scoreQuery 是一个查询变量,有时简称为“查询”。查询变量并不存储实际的结果数据(这些数据是在 **foreach** 循环中产生的)。另外,当 **foreach** 语句执行时,查询结果并不是通过查询变量 scoreQuery 返回的。相反,它们是通过迭代变量 testScore 返回的。可以在另一个 **foreach** 循环中迭代 scoreQuery 变量。只要该变量和数据源都没有修改,该变量都将产生相同的结果。
查询变量可以存储用查询语法或方法语法(或二者的组合)表示的查询。在下面的示例中,queryMajorCities 和 queryMajorCities2 都是查询变量:
```
//Query syntax
IEnumerable<City> queryMajorCities =
from city in cities
where city.Population > 100000
select city;
// Method-based syntax
IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > 100000);
```
另一方面,下面的两个示例演示了不是查询变量的变量,即使每个变量都用查询进行了初始化。它们不是查询变量的原因是它们存储了结果:
```
int highestScore =
(from score in scores
select score)
.Max();
// or split the expression
IEnumerable<int> scoreQuery =
from score in scores
select score;
int highScore = scoreQuery.Max();
List<City> largeCitiesList =
(from country in countries
from city in country.Cities
where city.Population > 10000
select city)
.ToList();
// or split the expression
IEnumerable<City> largeCitiesQuery =
from country in countries
from city in country.Cities
where city.Population > 10000
select city;
List<City> largeCitiesList2 = largeCitiesQuery.ToList();
```
| ![](https://box.kancloud.cn/2016-01-31_56adb62c1380a.jpg) 注意 |
| :-- |
| 在 LINQ 文档中,存储查询的变量在其名称中包含单词“query”,而存储实际结果的变量在其名称中不包含单词“query”。 |
有关用于表示查询的不同方式的更多信息,请参见[Query Syntax and Method Syntax in LINQ (C#)](https://msdn.microsoft.com/zh-cn/library/bb397947.aspx)。
#### 查询变量的显式类型化和隐式类型化
本文档通常提供查询变量的显式类型,以便演示查询变量和 [select 子句](https://msdn.microsoft.com/zh-cn/library/bb384087.aspx)之间的类型关系。但是,也可以使用 [var](https://msdn.microsoft.com/zh-cn/library/bb383973.aspx) 关键字指示编译器在编译时推断查询变量(或任何其他本地变量)的类型。例如,还可以使用隐式类型化表示本主题前面部分中演示的查询示例:
```
// Use of var is optional here and in all queries.
// queryCities is an IEnumerable<City> just as
// when it is explicitly typed.
var queryCities =
from city in cities
where city.Population > 100000
select city;
```
有关更多信息,请参见[隐式类型的局部变量(C# 编程指南)](https://msdn.microsoft.com/zh-cn/library/bb384061.aspx)和 [Type Relationships in LINQ Query Operations (C#)](https://msdn.microsoft.com/zh-cn/library/bb397924.aspx)。
### 开始查询表达式
查询表达式必须以 **from** 子句开头。它同时指定了数据源和范围变量。在对源序列进行遍历的过程中,范围变量表示源序列中的每个后续元素。将根据数据源中元素的类型对范围变量进行强类型化。在下面的示例中,因为 countries 是 Country 对象数组,所以范围变量也被类型化为 Country,这样就可以使用点运算符来访问该类型的任何可用成员。
```
IEnumerable<Country> countryAreaQuery =
from country in countries
where country.Area > 500000 //sq km
select country;
```
在使用分号或延续子句退出查询之前,范围变量将一直位于范围中。
查询表达式可以包含多个 **from** 子句。当源序列中的每个元素本身就是集合或包含集合时,可使用附加的 **from** 子句。例如,假定您具有一个 Country 对象集合,而其中每个对象都包含一个名为 Cities 的 City 对象集合。若要查询每个 Country 中的 City 对象,请使用两个**from** 子句,如下所示:
```
IEnumerable<City> cityQuery =
from country in countries
from city in country.Cities
where city.Population > 10000
select city;
```
有关更多信息,请参见 [from 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb383978.aspx)。
### 结束查询表达式
查询表达式必须以 **select** 子句或 **group** 子句结尾。
#### group 子句
使用 **group** 子句可产生按照指定的键组织的组序列。键可以采用任何数据类型。例如,下面的查询创建一个组序列,该序列包含一个或多个 Country 对象,并且它的键是 **char** 值。
```
var queryCountryGroups =
from country in countries
group country by country.Name[0];
```
有关分组的更多信息,请参见 [group 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb384063.aspx)。
#### select 子句
使用 **select** 子句可产生所有其他类型的序列。简单的 **select** 子句只是产生与数据源中包含的对象具有相同类型的对象的序列。在此示例中,数据源包含 Country 对象。 **orderby** 子句只是将元素重新排序,而 **select** 子句则产生重新排序的 Country 对象的序列。
```
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
```
可以使用 **select** 子句将源数据转换为新类型的序列。这一转换也称为“投影”。在下面的示例中,**select** 子句对一个匿名类型序列进行投影,该序列仅包含原始元素中各字段的子集。请注意,新对象是使用对象初始值设定项初始化的。
```
// Here var is required because the query
// produces an anonymous type.
var queryNameAndPop =
from country in countries
select new { Name = country.Name, Pop = country.Population };
```
有关使用 **select** 子句转换源数据的所有方式的更多信息,请参见 [select 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb384087.aspx)。
#### 使用“into”进行延续
可以在 **select** 或 **group** 子句中使用 **into** 关键字来创建用于存储查询的临时标识符。当您必须在分组或选择操作之后对查询执行附加查询操作时,需要这样做。在下面的示例中,以一千万人口范围为界对 countries 进行分组。在创建这些组之后,使用附加子句筛选掉某些组,然后按升序对剩下的组进行排序。若要执行这些附加操作,需要使用由 countryGroup 表示的延续。
```
// percentileQuery is an IEnumerable<IGrouping<int, Country>>
var percentileQuery =
from country in countries
let percentile = (int) country.Population / 10000000
group country by percentile into countryGroup
where countryGroup.Key >= 20
orderby countryGroup.Key
select countryGroup;
// grouping is an IGrouping<int, Country>
foreach (var grouping in percentileQuery)
{
Console.WriteLine(grouping.Key);
foreach (var country in grouping)
Console.WriteLine(country.Name + ":" + country.Population);
}
```
有关更多信息,请参见 [into(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb311045.aspx)。
### 筛选、排序和联接
在 **from** 开始子句以及 **select** 或 **group** 结束子句之间,所有其他子句(**where**、**join**、**orderby**、**from**、**let**)都是可选的。任何可选子句都可以在查询正文中使用零次或多次。
#### where 子句
使用 **where** 子句可以根据一个或多个谓词表达式筛选掉源数据中的某些元素。以下示例中的 **where** 子句含有两个谓词。
```
IEnumerable<City> queryCityPop =
from city in cities
where city.Population < 200000 && city.Population > 100000
select city;
```
有关更多信息,请参见 [where 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb311043.aspx)。
#### orderby 子句
使用 **orderby** 子句可以按升序或降序对结果进行排序。您还可以指定次要排序顺序。下面的示例使用 Area 属性对 country 对象执行主要排序,然后使用 Population 属性执行次要排序。
```
IEnumerable<Country> querySortedCountries =
from country in countries
orderby country.Area, country.Population descending
select country;
```
**ascending** 关键字是可选的;如果未指定顺序,则它是默认排序顺序。有关更多信息,请参见 [orderby 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb383982.aspx)。
#### join 子句
使用 **join** 子句可以根据每个元素中指定键之间的相等比较,对一个数据源中的元素与另外一个数据源中的元素进行关联和/或组合。在 LINQ 中,联接操作是针对其元素具有不同类型的对象序列执行的。在联接两个序列之后,必须使用 **select** 或 **group** 语句指定要存储到输出序列中的元素。还可以使用匿名类型将每组关联元素中的属性组合为输出序列的新类型。下面的示例对其 Category 属性与 categories 字符串数组中的某个类别相匹配的 prod 对象进行关联。其 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 };
```
通过使用 [into](https://msdn.microsoft.com/zh-cn/library/bb311045.aspx) 关键字将 **join** 操作的结果存储到临时变量中,还可以执行分组联接。有关更多信息,请参见 [join 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb311040.aspx)。
#### let 子句
使用 **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(new char[] { ' ' })[0]
select firstName;
foreach (string s in queryFirstNames)
Console.Write(s + " ");
//Output: Svetlana Claire Sven Cesar
```
有关更多信息,请参见 [let 子句(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb383976.aspx)。
### 查询表达式中的子查询
查询子句本身可能包含一个查询表达式,该查询表达式有时称为“子查询”。每个子查询都以它自己的 **from** 子句开头,该子句不一定指向第一个 **from** 子句中的同一数据源。例如,下面的查询演示了一个在 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()
};
```
有关更多信息,请参见 [如何:对分组操作执行子查询(C# 编程指南)](https://msdn.microsoft.com/zh-cn/library/bb311041.aspx)。
## 请参阅
[C# 编程指南](https://msdn.microsoft.com/zh-cn/library/67ef8sbd.aspx)
[LINQ 查询表达式(C# 编程指南)](https://msdn.microsoft.com/zh-cn/library/bb397676.aspx)
[LINQ (Language-Integrated Query)](https://msdn.microsoft.com/zh-cn/library/bb397926.aspx)
[查询关键字(C# 参考)](https://msdn.microsoft.com/zh-cn/library/bb310804.aspx)
[Standard Query Operators Overview](https://msdn.microsoft.com/zh-cn/library/bb397896.aspx)
- C# 编程指南
- 在 C# 程序内部
- Hello World -- 您的第一个程序(C# 编程指南)
- C# 程序的通用结构(C# 编程指南)
- C# 编码约定(C# 编程指南)
- 数组(C# 编程指南)
- 作为对象的数组(C# 编程指南)
- 一维数组(C# 编程指南)
- 多维数组(C# 编程指南)
- 交错数组(C# 编程指南)
- 对数组使用 foreach(C# 编程指南)
- 将数组作为参数传递(C# 编程指南)
- 使用 ref 和 out 传递数组(C# 编程指南)
- 隐式类型的数组(C# 编程指南)
- 类和结构(C# 编程指南)
- 类(C# 编程指南)
- 对象(C# 编程指南)
- 结构(C# 编程指南)
- 继承(C# 编程指南)
- 多态性(C# 编程指南)
- 抽象类、密封类及类成员(C# 编程指南)
- 静态类和静态类成员(C# 编程指南)
- 成员(C# 编程指南)
- 访问修饰符(C# 编程指南)
- 字段(C# 编程指南)
- 常量(C# 编程指南)
- 属性(C# 编程指南)
- 方法(C# 编程指南)
- 构造函数(C# 编程指南)
- 析构函数(C# 编程指南)
- 对象和集合初始值设定项(C# 编程指南)
- 如何:使用 foreach 访问集合类(C# 编程指南)
- 嵌套类型(C# 编程指南)
- 分部类和方法(C# 编程指南)
- 匿名类型(C# 编程指南)
- 委托(C# 编程指南)
- 使用委托(C# 编程指南)
- 带有命名方法的委托与带有匿名方法的委托(C# 编程指南)
- 如何:合并委托(多路广播委托)(C# 编程指南)
- 如何:声明、实例化和使用委托(C# 编程指南)
- 枚举类型(C# 编程指南)
- 事件(C# 编程指南)
- 如何:订阅和取消订阅事件(C# 编程指南)
- 如何:发布符合 .NET Framework 准则的事件(C# 编程指南)
- 如何:在派生类中引发基类事件(C# 编程指南)
- 如何:实现接口事件(C# 编程指南)
- 如何:使用字典存储事件实例(C# 编程指南)
- 如何:实现自定义事件访问器(C# 编程指南)
- 异常和异常处理(C# 编程指南)
- 使用异常(C# 编程指南)
- 异常处理(C# 编程指南)
- 创建和引发异常(C# 编程指南)
- 编译器生成的异常(C# 编程指南)
- 如何:使用 try/catch 处理异常(C# 编程指南)
- 如何:使用 finally 执行清理代码(C# 编程指南)
- 如何:捕捉非 CLS 异常
- 文件系统和注册表(C# 编程指南)
- 如何:循环访问目录树(C# 编程指南)
- 如何:获取有关文件、文件夹和驱动器的信息(C# 编程指南)
- 如何:创建文件或文件夹(C# 编程指南)
- 如何:复制、删除和移动文件和文件夹(C# 编程指南)
- 如何:提供文件操作进度对话框(C# 编程指南)
- 如何:写入文本文件(C# 编程指南)
- 如何:读取文本文件中的内容(C# 编程指南)
- 如何:一次一行地读取文本文件 (Visual C#)
- 如何:在注册表中创建注册表项 (Visual C#)
- 泛型(C# 编程指南)
- 泛型介绍(C# 编程指南)
- 泛型的优点(C# 编程指南)
- 泛型类型参数(C# 编程指南)
- 类型参数的约束(C# 编程指南)
- 泛型类(C# 编程指南)
- 泛型接口(C# 编程指南)
- 泛型方法(C# 编程指南)
- 泛型和数组(C# 编程指南)
- 泛型委托(C# 编程指南)
- 泛型代码中的默认关键字(C# 编程指南)
- C++ 模板和 C# 泛型之间的区别(C# 编程指南)
- 运行时中的泛型(C# 编程指南)
- .NET Framework 类库中的泛型(C# 编程指南)
- 泛型和反射(C# 编程指南)
- 泛型和特性(C# 编程指南)
- 索引器(C# 编程指南)
- 使用索引器(C# 编程指南)
- 接口中的索引器(C# 编程指南)
- 属性和索引器之间的比较(C# 编程指南)
- 接口(C# 编程指南)
- 显式接口实现(C# 编程指南)
- 如何:显式实现接口成员(C# 编程指南)
- 如何:显式实现两个接口的成员(C# 编程指南)
- 互操作性(C# 编程指南)
- 互操作性概述(C# 编程指南)
- 如何:通过使用 Visual C# 功能访问 Office 互操作对象(C# 编程指南)
- 如何:在 COM 互操作编程中使用索引属性(C# 编程指南)
- 如何:使用平台调用播放波形文件(C# 编程指南)
- 演练:Office 编程(C# 和 Visual Basic)
- COM 类示例(C# 编程指南)
- LINQ 查询表达式(C# 编程指南)
- 查询表达式基础(C# 编程指南)
- 如何:在 C# 中编写 LINQ 查询
- 如何:查询对象集合(C# 编程指南)
- 如何:从方法中返回查询(C# 编程指南)
- 如何:在内存中存储查询结果(C# 编程指南)
- 如何:对查询结果进行分组(C# 编程指南)
- 如何:创建嵌套组(C# 编程指南)
- 如何:对分组操作执行子查询(C# 编程指南)
- 如何:按连续键对结果进行分组(C# 编程指南)
- 如何:在运行时动态指定谓词筛选器(C# 编程指南)
- 如何:执行内部联接(C# 编程指南)
- 如何:执行分组联接(C# 编程指南)
- 如何:执行左外部联接(C# 编程指南)
- 如何:对 Join 子句的结果进行排序(C# 编程指南)
- 如何:使用复合键进行联接(C# 编程指南)
- 如何:执行自定义联接操作(C# 编程指南)
- 如何:在查询表达式中处理 Null 值(C# 编程指南)
- 如何:在查询表达式中处理异常(C# 编程指南)
- Main() 和命令行参数(C# 编程指南)
- 命令行参数(C# 编程指南)
- 如何:显示命令行参数(C# 编程指南)
- 如何:使用 foreach 访问命令行参数(C# 编程指南)
- Main() 返回值(C# 编程指南)
- 命名空间(C# 编程指南)
- 使用命名空间(C# 编程指南)
- 如何:使用全局命名空间别名(C# 编程指南)
- 如何:使用 My 命名空间(C# 编程指南)
- 可以为 null 的类型(C# 编程指南)
- 使用可以为 null 的类型(C# 编程指南)
- 装箱可以为 null 的类型(C# 编程指南)
- 如何:标识可以为 null 的类型(C# 编程指南)
- 如何:安全地将 bool? 强制转换为 bool(C# 编程指南)
- 语句、表达式和运算符(C# 编程指南)
- 语句(C# 编程指南)
- 表达式(C# 编程指南)
- 运算符(C# 编程指南)
- 匿名函数(C# 编程指南)
- 可重载运算符(C# 编程指南)
- 转换运算符(C# 编程指南)
- 如何:使用运算符重载创建复数类(C# 编程指南)
- 相等比较(C# 编程指南)
- 字符串(C# 编程指南)
- 如何:串联多个字符串(C# 编程指南)
- 如何:修改字符串内容(C# 编程指南)
- 如何:比较字符串(C# 编程指南)
- 如何:拆分字符串(C# 编程指南)
- 如何:使用字符串方法搜索字符串(C# 编程指南)
- 如何:使用正则表达式搜索字符串(C# 编程指南)
- 如何:确定字符串是否表示数值(C# 编程指南)
- 如何:将字符串转换为 DateTime(C# 编程指南)
- 如何:在旧式编码与 Unicode 之间转换(C# 编程指南)
- 如何:将 RTF 转换为纯文本(C# 编程指南)
- 类型(C# 编程指南)
- 强制转换和类型转换(C# 编程指南)
- 装箱和取消装箱(C# 编程指南)
- 使用类型 dynamic(C# 编程指南)
- 如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南)
- 如何:将字节数组转换为 int(C# 编程指南)
- 如何:将字符串转换为数字(C# 编程指南)
- 如何:在十六进制字符串与数值类型之间转换(C# 编程指南)
- 不安全代码和指针(C# 编程指南)
- 固定大小的缓冲区(C# 编程指南)
- 指针类型(C# 编程指南)
- XML 文档注释(C# 编程指南)
- 建议的文档注释标记(C# 编程指南)
- 处理 XML 文件(C# 编程指南)
- 文档标记的分隔符(C# 编程指南)
- 如何:使用 XML 文档功能(C# 编程指南)
- C# 参考
- C# 关键字
- 类型(C# 参考)
- 值类型(C# 参考)
- bool(C# 参考)
- byte(C# 参考)
- char(C# 参考)
- decimal(C# 参考)
- double(C# 参考)
- enum(C# 参考)
- float(C# 参考)
- int(C# 参考)
- long(C# 参考)
- sbyte(C# 参考)
- short(C# 参考)
- struct(C# 参考)
- uint(C# 参考)
- ulong(C# 参考)
- ushort(C# 参考)
- 引用类型(C# 参考)
- class(C# 参考)
- 委托(C# 参考)
- dynamic(C# 参考)
- 接口(C# 参考)
- object(C# 参考)
- string(C# 参考)
- 内插字符串(C# 和 Visual Basic 引用)
- void(C# 参考)
- var(C# 参考)
- 类型参考表(C# 参考)
- 内置类型表(C# 参考)
- 整型表(C# 参考)
- 浮点型表(C# 参考)
- 默认值表(C# 参考)
- 值类型表(C# 参考)
- 隐式数值转换表(C# 参考)
- 显式数值转换表(C# 参考)
- 设置数值结果表的格式(C# 参考)
- 修饰符(C# 参考)
- 访问修饰符(C# 参考)
- 可访问性级别(C# 参考)
- 可访问域(C# 参考)
- 可访问性级别的使用限制(C# 参考)
- internal(C# 参考)
- private(C# 参考)
- protected(C# 参考)
- public(C# 参考)
- abstract(C# 参考)
- async(C# 参考)
- const(C# 参考)
- event(C# 参考)
- extern(C# 参考)
- in(泛型修饰符)(C# 参考)
- out(泛型修饰符)(C# 参考)
- override(C# 参考)
- readonly(C# 参考)
- sealed(C# 参考)
- static(C# 参考)
- unsafe(C# 参考)
- virtual(C# 参考)
- volatile(C# 参考)
- 语句关键字(C# 参考)
- 选择语句(C# 参考)
- if-else(C# 参考)
- switch(C# 参考)
- 迭代语句(C# 参考)
- do(C# 参考)
- for(C# 参考)
- foreach,in(C# 参考)
- while(C# 参考)
- 跳转语句(C# 参考)
- break(C# 参考)
- continue(C# 参考)
- goto(C# 参考)
- return(C# 参考)
- 异常处理语句(C# 参考)
- throw(C# 参考)
- try-catch(C# 参考)
- try-finally(C# 参考)
- try-catch-finally(C# 参考)
- Checked 和 Unchecked(C# 参考)
- checked(C# 参考)
- unchecked(C# 参考)
- fixed 语句(C# 参考)
- “锁定”语句(C# 参考)
- 方法参数(C# 参考)
- params(C# 参考)
- ref(C# 参考)
- out(C# 参考)
- out 参数修饰符(C# 参考)
- 命名空间关键字(C# 参考)
- 命名空间(C# 参考)
- using(C# 参考)
- using 指令(C# 参考)
- using 语句(C# 参考)
- 外部别名(C# 参考)
- 运算符关键字(C# 参考)
- as(C# 参考)
- await(C# 参考)
- is(C# 参考)
- new(C# 参考)
- new 运算符(C# 参考)
- new 修饰符(C# 参考)
- new 约束(C# 参考)
- sizeof(C# 参考)
- typeof(C# 参考)
- true(C# 参考)
- true 运算符(C# 参考)
- true 字面常数(C# 参考)
- false(C# 参考)
- false 运算符(C# 参考)
- false 字面常数(C# 参考)
- stackalloc(C# 参考)
- nameof(C# 和 Visual Basic 引用)
- 转换关键字(C# 参考)
- explicit(C# 参考)
- implicit(C# 参考)
- 运算符(C# 参考)
- 访问关键字(C# 参考)
- base(C# 参考)
- this(C# 参考)
- 文字关键字(C# 参考)
- null(C# 参考)
- default(C# 参考)
- 上下文关键字(C# 参考)
- add(C# 参考)
- get(C# 参考)
- global(C# 参考)
- 分部(类型)(C# 参考)
- 分部(方法)(C# 参考)
- remove(C# 参考)
- set(C# 参考)
- where(泛型类型约束)(C# 参考)
- value(C# 参考)
- yield(C# 参考)
- 查询关键字(C# 参考)
- from 子句(C# 参考)
- where 子句(C# 参考)
- select 子句(C# 参考)
- group 子句(C# 参考)
- into(C# 参考)
- orderby 子句(C# 参考)
- join 子句(C# 参考)
- let 子句(C# 参考)
- ascending(C# 参考)
- descending(C# 参考)
- on(C# 参考)
- equals(C# 参考)
- by(C# 参考)
- in(C# 参考)
- C# 运算符
- 运算符(C# 参考)
- () 运算符(C# 参考)
- . 运算符(C# 参考)
- :: 运算符(C# 参考)
- + 运算符(C# 参考)
- - 运算符(C# 参考)
- * 运算符(C# 参考)
- / 运算符(C# 参考)
- % 运算符(C# 参考)
- & 运算符(C# 参考)
- | 运算符(C# 参考)
- ^ 运算符(C# 参考)
- ! 运算符(C# 参考)
- ~ 运算符(C# 参考)
- = 运算符(C# 参考)
- &lt; 运算符(C# 参考)
- &gt; 运算符(C# 参考)
- ?: 运算符(C# 参考)
- ++ 运算符(C# 参考)
- -- 运算符(C# 参考)
- && 运算符(C# 参考)
- || 运算符(C# 参考)
- &lt;&lt; 运算符(C# 参考)
- &gt;&gt; 运算符(C# 参考)
- == 运算符(C# 参考)
- != 运算符(C# 参考)
- &lt;= 运算符(C# 参考)
- &gt;= 运算符(C# 参考)
- += 运算符(C# 参考)
- -= 运算符(C# 参考)
- *= 运算符(C# 参考)
- /= 运算符(C# 参考)
- %= 运算符(C# 参考)
- &= 运算符(C# 参考)
- |= 运算符(C# 参考)
- ^= 运算符(C# 参考)
- &lt;&lt;= 运算符(C# 参考)
- &gt;&gt;= 运算符(C# 参考)
- -&gt; 运算符(C# 参考)
- ?? 运算符(C# 参考)
- =&gt; 运算符(C# 参考)
- NULL 条件运算符(C# 和 Visual Basic)
- C# 预处理器指令
- #if(C# 参考)
- #else(C# 参考)
- #elif(C# 参考)
- #endif(C# 参考)
- #define(C# 参考)
- #undef(C# 参考)
- #warning(C# 参考)
- #error(C# 参考)
- #line(C# 参考)
- #region(C# 参考)
- #endregion(C# 参考)
- #pragma(C# 参考)
- #pragma warning(C# 参考)
- #pragma checksum(C# 参考)
- C# Compiler Options
- Command-line Building With csc.exe
- How to: Set Environment Variables for the Visual Studio Command Line
- Deployment of C# Applications
- C# Compiler Options Listed by Category
- C# Compiler Options Listed Alphabetically
- @ (C# Compiler Options)
- /addmodule (C# Compiler Options)
- /appconfig (C# Compiler Options)
- /baseaddress (C# Compiler Options)
- /bugreport (C# Compiler Options)
- /checked (C# Compiler Options)
- /codepage (C# Compiler Options)
- /debug (C# Compiler Options)
- /define (C# Compiler Options)
- /delaysign (C# Compiler Options)
- /doc (C# Compiler Options)
- /errorreport (C# Compiler Options)
- /filealign (C# Compiler Options)
- /fullpaths (C# Compiler Options)
- /help, /? (C# Compiler Options)
- /highentropyva (C# Compiler Options)
- /keycontainer (C# Compiler Options)
- /keyfile (C# Compiler Options)
- /langversion (C# Compiler Options)
- /lib (C# Compiler Options)
- /link (C# Compiler Options)
- /linkresource (C# Compiler Options)
- /main (C# Compiler Options)
- /moduleassemblyname (C# Compiler Option)
- /noconfig (C# Compiler Options)
- /nologo (C# Compiler Options)
- /nostdlib (C# Compiler Options)
- /nowarn (C# Compiler Options)
- /nowin32manifest (C# Compiler Options)
- /optimize (C# Compiler Options)
- /out (C# Compiler Options)
- /pdb (C# Compiler Options)
- /platform (C# Compiler Options)
- /preferreduilang (C# Compiler Options)
- /recurse (C# Compiler Options)
- /reference (C# Compiler Options)
- /resource (C# Compiler Options)
- /subsystemversion (C# Compiler Options)
- /target (C# Compiler Options)
- /target:appcontainerexe(C# 编译器选项)
- /target:exe (C# Compiler Options)
- /target:library (C# Compiler Options)
- /target:module (C# Compiler Options)
- /target:winexe (C# Compiler Options)
- /target:winmdobj(C# 编译器选项)
- /unsafe (C# Compiler Options)
- /utf8output (C# Compiler Options)
- /warn (C# Compiler Options)
- /warnaserror (C# Compiler Options)
- /win32icon (C# Compiler Options)
- /win32manifest (C# Compiler Options)
- /win32res (C# Compiler Options)
- C# Compiler Errors
- Compiler Error CS0001
- Compiler Error CS0006
- Compiler Error CS0007
- 编译器错误 CS0015
- Compiler Error CS0016
- Compiler Error CS0019
- Compiler Error CS0029
- Compiler Error CS0034
- Compiler Error CS0038
- Compiler Error CS0039
- Compiler Error CS0050
- Compiler Error CS0051
- Compiler Error CS0052
- Compiler Error CS0071
- Compiler Error CS0103
- Compiler Error CS0106
- Compiler Error CS0115
- Compiler Error CS0116
- Compiler Error CS0120
- Compiler Error CS0122
- Compiler Error CS0134
- Compiler Error CS0151
- 编译器错误 CS0163
- Compiler Error CS0165
- Compiler Error CS0173
- Compiler Error CS0178
- Compiler Error CS0188
- Compiler Error CS0201
- Compiler Error CS0229
- Compiler Error CS0233
- Compiler Error CS0234
- Compiler Error CS0246
- Compiler Error CS0260
- Compiler Error CS0266
- Compiler Error CS0269
- Compiler Error CS0270
- Compiler Error CS0304
- Compiler Error CS0310
- Compiler Error CS0311
- Compiler Error CS0413
- Compiler Error CS0417
- Compiler Error CS0433
- Compiler Error CS0445
- Compiler Error CS0446
- Compiler Error CS0504
- 编译器错误 CS0507
- Compiler Error CS0518
- Compiler Error CS0523
- Compiler Error CS0545
- Compiler Error CS0552
- Compiler Error CS0563
- Compiler Error CS0570
- Compiler Error CS0571
- Compiler Error CS0579
- Compiler Error CS0592
- Compiler Error CS0616
- Compiler Error CS0650
- Compiler Error CS0686
- Compiler Error CS0702
- 编译器错误 CS0703
- Compiler Error CS0731
- Compiler Error CS0826
- Compiler Error CS0834
- Compiler Error CS0840
- 编译器错误 CS0843
- Compiler Error CS0845
- Compiler Error CS1001
- Compiler Error CS1009
- Compiler Error CS1018
- Compiler Error CS1019
- Compiler Error CS1026
- Compiler Error CS1029
- Compiler Error CS1061
- Compiler Error CS1112
- 编译器错误 CS1501
- Compiler Error CS1502
- Compiler Error CS1519
- Compiler Error CS1540
- Compiler Error CS1546
- Compiler Error CS1548
- Compiler Error CS1564
- Compiler Error CS1567
- Compiler Error CS1579
- Compiler Error CS1612
- Compiler Error CS1614
- Compiler Error CS1640
- Compiler Error CS1644
- Compiler Error CS1656
- Compiler Error CS1674
- Compiler Error CS1703
- Compiler Error CS1704
- Compiler Error CS1705
- Compiler Error CS1708
- Compiler Error CS1716
- 编译器错误 CS1721
- Compiler Error CS1726
- Compiler Error CS1729
- Compiler Error CS1919
- Compiler Error CS1921
- Compiler Error CS1926
- Compiler Error CS1933
- Compiler Error CS1936
- Compiler Error CS1941
- Compiler Error CS1942
- Compiler Error CS1943
- Compiler Error CS1946
- 编译器错误 CS2032
- Compiler Warning (level 1) CS0420
- Compiler Warning (level 1) CS0465
- Compiler Warning (level 1) CS1058
- Compiler Warning (level 1) CS1060
- Compiler Warning (level 1) CS1598
- Compiler Warning (level 1) CS1607
- Compiler Warning (level 1) CS1616
- Compiler Warning (level 1) CS1658
- Compiler Warning (level 1) CS1683
- Compiler Warning (level 1) CS1685
- Compiler Warning (level 1) CS1690
- Compiler Warning (level 1) CS1691
- Compiler Warning (level 1) CS1699
- Compiler Warning (level 1) CS1762
- Compiler Warning (level 1) CS1956
- Compiler Warning (level 1) CS3003
- Compiler Warning (level 1) CS3007
- Compiler Warning (level 1) CS3009
- 编译器警告(等级 1)CS4014
- Compiler Warning (level 2) CS0108
- 编译器警告(等级 2)CS0467
- Compiler Warning (level 2) CS0618
- Compiler Warning (level 2) CS1701
- Compiler Warning (level 3) CS0675
- Compiler Warning (level 3) CS1700
- Compiler Warning (level 4) CS0429
- Compiler Warning (level 4) CS1591
- Compiler Warning (level 4) CS1610
- C# 语言规范