# 演练:Office 编程(C# 和 Visual Basic)
Visual Studio 2010 在 C# 和 Visual Basic 中引入了改进 Microsoft Office 编程的新功能。每种语言都增加了其他语言中已经存在的功能。
C# 中的新功能包括命名参数和可选参数、具有 **dynamic** 类型的返回值,以及在 COM 编程中忽略 **ref** 关键字和访问索引属性的功能。Visual Basic 中的新功能包括自动实现的属性、Lambda 表达式语句和集合初始值设定项。
两种语言都支持嵌入类型信息,从而允许在不向用户的计算机部署主互操作程序集 (PIA) 的情况下部署与 COM 组件交互的程序集。有关详细信息,请参阅[演练:嵌入托管程序集中的类型(C# 和 Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dd409610.aspx)。
本演练演示 Office 编程环境中的新功能,但这些新功能在常规编程中也极为有用。在本演练中,你将首先使用 Excel 外接应用程序来创建 Excel 工作簿。然后,你将创建包含工作簿链接的 Word 文档。最后,你将看到可以如何开启和关闭 PIA 依赖项。
## 系统必备
若要完成本演练,你的计算机上必须安装有 Microsoft Office Excel 2013(或者 2007 或更高版本)和 Microsoft Office Word 2013(或者 2007 或更高版本)。
如果你使用的操作系统早于 Windows Vista,请确保安装 .NET Framework 2.0。
| ![](https://box.kancloud.cn/2016-01-31_56adb62c1380a.jpg) 注意 |
| :-- |
| 以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 这些元素取决于你所使用的 Visual Studio 版本和你所使用的设置。 有关详细信息,请参阅[个性化 Visual Studio IDE](https://msdn.microsoft.com/zh-CN/library/mt269425.aspx)。 |
## 设置 Excel 外接应用程序
1. 启动 Visual Studio。
2. 在**“文件”**菜单上,指向**“新建”**,然后单击**“项目”**。
3. 在“安装的模板”窗格中,展开“Visual Basic”或“Visual C#”,再展开“Office”,然后单击“2013”(或“2010”或“2007”)。
4. 在“模板”窗格中,单击“Excel 2013 外接应用程序”(或“Excel 2010 外接应用程序”或“Excel 2007 外接应用程序”)。
5. 查看“模板”窗格的顶部,确保“.NET Framework 4”或更高版本出现在“目标框架”框中。
6. 如果需要,在“名称”框中键入项目的名称。
7. 单击“确定”。
8. 新项目将出现在“解决方案资源管理器”中。
## 添加引用
1. 在“解决方案资源管理器”中,右键单击你的项目名称,然后单击“添加引用”。将显示**“添加引用”**对话框。
2. 在“程序集”选项卡上,在“组件名称”列表中选择“Microsoft.Office.Interop.Excel”版本 15.0.0.0(针对 Excel 2010,选择版本 14.0.0.0;针对 Excel 2007,选择版本 12.0.0.0),然后按住 Ctrl 键并选择“Microsoft.Office.Interop.Word”版本 15.0.0.0(针对 Word 2010,选择版本 14.0.0.0;针对 Word 2007,选择版本 12.0.0.0)。如果未看到程序集,你可能需要确保安装并显示它们(参阅[如何:安装 Office 主互操作程序集](https://msdn.microsoft.com/zh-CN/library/kh3965hw.aspx))。
3. 单击“确定”。
## 添加必要的 Imports 语句或 using 指令
1. 在“解决方案资源管理器”中,右键单击“ThisAddIn.vb”或“ThisAddIn.cs”文件,然后单击“查看代码”。
2. 将以下 **Imports** 语句 (Visual Basic) 或 **using** 指令 (C#) 添加到代码文件的顶部(如果不存在)。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1)
```
using System.Collections.Generic;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
```
## 创建银行帐户列表
1. 在“解决方案资源管理器”中,右键单击你的项目名称,单击“添加”,然后单击“类”。如果使用的是 Visual Basic,则将类命名为 Account.vb;如果使用的是 C#,则将类命名为 Account.cs。单击**“添加”**。
2. 将 Account 类的定义替换为以下代码。类定义使用_“自动实现的属性”_,在 Visual Studio 2010 中,是 Visual Basic 的新功能。有关详细信息,请参阅[自动实现的属性 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dd293589.aspx)。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2)
```
class Account
{
public int ID { get; set; }
public double Balance { get; set; }
}
```
3. 若要创建包含两个帐户的 bankAccounts 列表,请将以下代码添加到 ThisAddIn.vb 或 ThisAddIn.cs 中的 ThisAddIn_Startup 方法。列表声明使用_“集合初始值设定项”_,在 Visual Studio 2010 中,是 Visual Basic 的新功能。有关详细信息,请参阅[集合初始值设定项 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dd293617.aspx)。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-3)
```
var bankAccounts = new List<Account>
{
new Account
{
ID = 345,
Balance = 541.27
},
new Account
{
ID = 123,
Balance = -127.44
}
};
```
## 将数据导出到 Excel
1. 在相同的文件中,将以下方法添加到 ThisAddIn 类。该方法设置 Excel 工作薄并将数据导出到工作簿。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-4)
```
void DisplayInExcel(IEnumerable<Account> accounts,
Action<Account, Excel.Range> DisplayFunc)
{
var excelApp = this.Application;
// Add a new Excel workbook.
excelApp.Workbooks.Add();
excelApp.Visible = true;
excelApp.Range["A1"].Value = "ID";
excelApp.Range["B1"].Value = "Balance";
excelApp.Range["A2"].Select();
foreach (var ac in accounts)
{
DisplayFunc(ac, excelApp.ActiveCell);
excelApp.ActiveCell.Offset[1, 0].Select();
}
// Copy the results to the Clipboard.
excelApp.Range["A1:B3"].Copy();
}
```
此方法使用 C# 的两项新功能。Visual Basic 中已存在这两项功能。
* 方法 [Add](http://go.microsoft.com/fwlink/?LinkId=210910) 有一个_“可选参数”_,用于指定特定的模板。如果希望使用形参的默认值,你可以借助可选形参(Visual C# 2010 中新增)忽略该形参的实参。由于上一个示例中未发送任何参数,**Add** 将使用默认模板并创建新的工作簿。C# 早期版本中的等效语句要求占位符参数:excelApp.Workbooks.Add(Type.Missing).
有关详细信息,请参阅[命名实参和可选实参(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/dd264739.aspx)。
* [Range](http://go.microsoft.com/fwlink/?LinkId=210911) 对象的 **Range** 和 **Offset** 属性使用_“索引属性”_功能。此功能允许你通过以下典型 C# 语法从 COM 类型使用这些属性。索引属性还允许你使用 **Range** 对象的 **Value** 属性,因此不必使用 **Value2** 属性。 **Value** 属性已编入索引,但索引是可选的。在以下示例中,可选参数和索引属性配合使用。
```
// Visual C# 2010 provides indexed properties for COM programming.
excelApp.Range["A1"].Value = "ID";
excelApp.ActiveCell.Offset[1, 0].Select();
```
在早期版本的语言中,需要以下特殊语法。
```
// In Visual C# 2008, you cannot access the Range, Offset, and Value
// properties directly.
excelApp.get_Range("A1").Value2 = "ID";
excelApp.ActiveCell.get_Offset(1, 0).Select();
```
你不能创建自己的索引属性。该功能仅支持使用现有索引属性。
有关详细信息,请参阅[如何:在 COM 互操作编程中使用索引属性(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/ee310208.aspx)。
2. 在 DisplayInExcel 的末尾添加以下代码以将列宽调整为适合内容。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-7)
```
excelApp.Columns[1].AutoFit();
excelApp.Columns[2].AutoFit();
```
这些添加展示 C# 2010 中的另一项新功能:处理从 COM 主机返回的 **Object** 值(如 Office),就像它们具有 [dynamic](https://msdn.microsoft.com/zh-CN/library/dd264741.aspx) 类型一样。当“嵌入互操作类型”设置为其默认值 **True** 时,或者由 [/link](https://msdn.microsoft.com/zh-CN/library/dd264728.aspx) 编译器选项引用程序集时,自动发生这种情况。键入 **dynamic** 允许后期绑定(Visual Basic 已提供该功能)并可避免 Visual C# 2008 和早期版本的语言中要求的显式强制转换。
例如,excelApp.Columns[1] 返回 **Object**,并且 **AutoFit** 是 Excel 的 [Range](http://go.microsoft.com/fwlink/?LinkId=210911) 方法。如果没有 **dynamic**,你必须将 excelApp.Columns[1] 返回的对象强制转换为 Range 的实例,然后才能调用 AutoFit 方法。
```
// Casting is required in Visual C# 2008.
((Excel.Range)excelApp.Columns[1]).AutoFit();
// Casting is not required in Visual C# 2010.
excelApp.Columns[1].AutoFit();
```
有关嵌入互操作类型的详细信息,请参阅本主题后面部分的“查找 PIA 引用”和“还原 PIA 依赖项”程序。有关 **dynamic** 的详细信息,请参阅 [dynamic(C# 参考)](https://msdn.microsoft.com/zh-CN/library/dd264741.aspx) 或 [使用类型 dynamic(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/dd264736.aspx)。
## 调用 DisplayInExcel
1. 在 ThisAddIn_StartUp 方法的末尾添加以下代码。对 DisplayInExcel 的调用包含两个参数。第一个参数是要处理的帐户列表的名称。第二个参数是定义如何处理数据的多行 lambda 表达式。每个帐户的 ID 和 balance 值都显示在相邻的单元格中,如果余额小于零,则相应的行显示为红色。多行 lambda 表达式是 Visual Basic 2010 中的新功能。有关详细信息,请参阅[Lambda 表达式 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/bb531253.aspx)。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-9)
```
DisplayInExcel(bankAccounts, (account, cell) =>
// This multiline lambda expression sets custom processing rules
// for the bankAccounts.
{
cell.Value = account.ID;
cell.Offset[0, 1].Value = account.Balance;
if (account.Balance < 0)
{
cell.Interior.Color = 255;
cell.Offset[0, 1].Interior.Color = 255;
}
});
```
2. 若要运行程序,请按 F5。出现包含帐户数据的 Excel 工作表。
## 添加 Word 文档
1. 在 ThisAddIn_StartUp 方法末尾添加以下代码,以创建包含指向 Excel 工作簿的链接的 Word 文档。
[VB](https://msdn.microsoft.com/zh-CN/library/ee342218.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-10)
```
var wordApp = new Word.Application();
wordApp.Visible = true;
wordApp.Documents.Add();
wordApp.Selection.PasteSpecial(Link: true, DisplayAsIcon: true);
```
此代码展示 C# 中的几项新功能:在 COM 编程中忽略 **ref** 的功能、命名参数以及可选参数。Visual Basic 中已存在这些功能。 [PasteSpecial](http://go.microsoft.com/fwlink/?LinkId=147099) 方法有七个参数,每个参数都是可选引用参数。在 Visual C# 2010 之前,你必须为这七个形参定义用作实参的对象变量,即使你没有有意义的值发送。通过命名实参和可选实参,你可以指定希望按名称访问的形参并仅将实参发送到这些形参。在本示例中,发送实参以指示应创建指向剪贴板上工作簿的链接(形参 Link)并指示该链接应在 Word 文档中显示为图标(形参 DisplayAsIcon)。Visual C# 2010 还允许你忽略这些参数的 **ref** 关键字。将 Visual C# 2008 的以下代码段与 Visual C# 2010 中需要的单行进行比较:
```
// Call to PasteSpecial in Visual C# 2008.
object iconIndex = Type.Missing;
object link = true;
object placement = Type.Missing;
object displayAsIcon = true;
object dataType = Type.Missing;
object iconFileName = Type.Missing;
object iconLabel = Type.Missing;
wordApp.Selection.PasteSpecial(ref iconIndex,
ref link,
ref placement,
ref displayAsIcon,
ref dataType,
ref iconFileName,
ref iconLabel);
// Call to PasteSpecial in Visual C# 2010.
wordApp.Selection.PasteSpecial(Link: true, DisplayAsIcon: true);
```
## 运行应用程序
1. 按 F5 运行该应用程序。Excel 启动并显示包含 bankAccounts 中两个帐户的信息的表。然后,出现包含指向 Excel 表的 Word 文档。
## 清理已完成的项目
1. 在 Visual Studio 中,单击“生成”菜单上的“清理解决方案”。否则,每次在计算机上打开 Excel 时都会运行外接应用程序。
## 查找 PIA 引用
1. 再次运行应用程序,但不单击“清理解决方案”。
2. 在“开始”菜单上,单击“所有程序”。接下来依次单击“Microsoft Visual Studio 2013”、“Visual Studio 工具”、“Visual Studio 命令提示符 (2013)”。
3. 在 Visual Studio 命令提示符 (2013) 窗口中键入 **ildasm**,然后按 Enter。此时将出现 IL DASM 窗口。
4. 在 IL DASM 窗口的“文件”菜单上,单击“打开”。双击“Visual Studio 2013”,然后双击“项目”。打开项目的文件夹,在 bin/Debug 文件夹中查找 _项目名称_.dll。双击 _项目名称_.dll。新窗口将显示项目的属性以及对其他模块和程序集的引用。注意,命名空间 **Microsoft.Office.Interop.Excel** 和 **Microsoft.Office.Interop.Word** 包含在程序集中。在 Visual Studio 2013 中,编译器默认将你需要的类型从引用的 PIA 导入程序集。
有关详细信息,请参阅[如何:查看程序集内容](https://msdn.microsoft.com/zh-CN/library/ceats605.aspx)。
5. 双击“清单”图标。此时将出现包含程序集列表的窗口,这些程序集包含项目所引用的项。 **Microsoft.Office.Interop.Excel** 和 **Microsoft.Office.Interop.Word** 未包含在列表中。由于项目需要的类型已导入程序集中,因此不需要引用 PIA。这使得部署变得更加容易。用户的计算机上不必存在 PIA,因为应用程序不需要部署特定版本的 PIA,应用程序可设计为与多个版本的 Office 配合使用,前提是所有版本中都存在必要的 API。
由于不再需要部署 PIA,你可以提前创建可与多个版本的 Office(包括之前的版本)配合使用的应用程序。但是,仅当你的代码不使用你当前所使用 Office 版本中不可用的任何 API 时,此情况才适用。特殊 API 在早期版本中是否可用并不始终明确,因此不建议使用早期版本的 Office。
6. 关闭清单窗口和程序集窗口。
| ![](https://box.kancloud.cn/2016-01-31_56adb62c1380a.jpg) 注意 |
| :-- |
| 在 Office 2003 以前,Office 并不发布 PIA。因此,生成适用于 Office 2002 或早期版本的互操作程序集的唯一方法是导入 COM 引用。 |
## 还原 PIA 依赖项
1. 在“解决方案资源管理器”中,单击“显示所有文件”按钮。展开“引用”文件夹并选择“Microsoft.Office.Interop.Excel”。按 F4 以显示**“属性”**窗口。
2. 在“属性”窗口中,将“嵌入互操作类型”属性从“True”更改为“False”。
3. 对 **Microsoft.Office.Interop.Word** 重复此程序中的步骤 1 和 2。
4. 在 C# 中,在 DisplayInExcel 方法的末尾注释掉对 Autofit 的两次调用。
5. 按 F5 以验证项目是否仍正确运行。
6. 重复上一个程序的步骤 1-3 以打开程序集窗口。注意,**Microsoft.Office.Interop.Word** 和 **Microsoft.Office.Interop.Excel** 不再位于嵌入程序集列表中。
7. 双击“清单”图标并滚动引用程序集的列表。 **Microsoft.Office.Interop.Word** 和 **Microsoft.Office.Interop.Excel** 均位于列表中。由于应用程序引用 Excel 和 Word PIA 并且“嵌入互操作类型”属性设置为“False”,因此最终用户的计算机上必须存在两个程序集。
8. 在 Visual Studio 中,单击“生成”菜单上的“清理解决方案”以清理完成的项目。
## 请参阅
[自动实现的属性 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dd293589.aspx)
[自动实现的属性(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/bb384054.aspx)
[集合初始值设定项 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dd293617.aspx)
[对象和集合初始值设定项(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/bb384062.aspx)
[可选参数 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/f25e2b6b.aspx)
[按位置和名称传递参数 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/51wfzyw0.aspx)
[命名实参和可选实参(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/dd264739.aspx)
[早期绑定和后期绑定 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/0tcf61s1.aspx)
[dynamic(C# 参考)](https://msdn.microsoft.com/zh-CN/library/dd264741.aspx)
[使用类型 dynamic(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/dd264736.aspx)
[Lambda 表达式 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/bb531253.aspx)
[Lambda 表达式(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/bb397687.aspx)
[如何:在 COM 互操作编程中使用索引属性(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/ee310208.aspx)
[演练:嵌入 Microsoft Office 程序集中的类型信息(C# 和 Visual Basic)](https://msdn.microsoft.com/zh-CN/library/ee317478.aspx)
[演练:嵌入托管程序集中的类型(C# 和 Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dd409610.aspx)
[演练:创建你的第一个 Excel VSTO 外接程序](https://msdn.microsoft.com/zh-CN/library/cc668205.aspx)
[COM 互操作 (Visual Basic)](https://msdn.microsoft.com/zh-CN/library/6bw51z5z.aspx)
[互操作性(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/ms173184.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# 语言规范