语言功能规则的 C# 编译器选项

以下选项控制编译器如何解释语言功能。 新的 MSBuild 语法以粗体显示。 旧的 csc.exe 语法以 code style 显示。

  • CheckForOverflowUnderflow / -checked:生成溢出检查。
  • AllowUnsafeBlocks / -unsafe:允许 unsafe 代码。
  • DefineConstants / -define:定义条件编译符号。
  • LangVersion / -langversion:指定语言版本,如 default(最新主版本)或 latest(最新版本,包括次要版本)。
  • Nullable / -nullable:启用可为空上下文或可为空警告。

注意

有关为项目配置这些选项的详细信息,请参阅 编译器选项

CheckForOverflowUnderflow

CheckForOverflowUnderflow选项控制在整数算术溢出的情况下定义程序行为的默认溢出检查上下文。

<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>

CheckForOverflowUnderflowtrue时,默认上下文为已检查上下文并启用溢出检查。 CheckForOverflowUnderflowfalse时,默认上下文为未选中的上下文。 此选项的默认值为 false,这意味着已禁用溢出检查。

还可以使用 checked and unchecked 语句显式控制代码部分的溢出检查上下文。

有关溢出检查上下文如何影响操作及其影响的操作的信息,请参阅 文章 checkedunchecked 语句

AllowUnsafeBlocks

AllowUnsafeBlocks 编译器选项允许使用 unsafe 关键字的代码进行编译。 此选项的默认值为false,表示不允许不安全代码。

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

有关不安全代码的详细信息,请参阅不安全代码和指针

启用更新的内存安全规则

更新后的内存安全规则是 C# 15 和 .NET 11 中的预览功能。 它们使用两个独立的编译器设置:

  • 语言 preview 版本支持新的语法和指针放松。
  • 编译器 updated-memory-safety-rules 功能启用更新的规则,包括 要求不安全 的调用方义务,并导致编译器使用 MemorySafetyRulesAttribute 属性记录程序集中的选择。

将来的稳定 SDK 属性 MemorySafetyRules计划为功能退出预览(例如 <MemorySafetyRules>2</MemorySafetyRules>),但尚未实现该属性的第三个激活层。

对于项目,请使用这两个设置:

<PropertyGroup>
  <LangVersion>preview</LangVersion>
  <Features>$(Features);updated-memory-safety-rules</Features>
</PropertyGroup>

对于基于文件的程序,添加等效指令:

#:property Features=$(Features);updated-memory-safety-rules
#:property LangVersion=preview

AllowUnsafeBlocks 属性是独立的。 它控制源是否可以使用 unsafe 关键字。 项目可以启用更新的规则,而无需允许不安全的代码,在这种情况下,当调用需要不安全的 API 时,它会收到错误。

一个程序集是否对另一个程序集强制实施更新的规则取决于哪个方选择加入:

  • 更新模型调用方、更新模型被调用方:被调用方的 unsafe 标记通过元数据传输。 调用方在块中 unsafe 包装对需要不安全的成员的每个调用。
  • 更新模型调用方、原始模型被调用方:兼容模式将签名中具有指针类型的任何被调用方成员视为需要不安全,因此调用站点需要封闭 unsafe 块。 此模式使基于指针的 API 无法无提示地失去其 unsafe 要求。
  • 原始模型调用方、更新模型被调用方:原始指针规则仍适用。 由于原始模型调用方无法读取新标记,因此其签名中没有指针类型的要求不安全成员可从安全代码中调用。

DefineConstants

DefineConstants 选项将定义程序中所有源代码文件的符号。

<DefineConstants>name;name2</DefineConstants>

此选项指定要定义的一个或多个符号的名称。 DefineConstants 选项具有与 #define 预处理器指令相同的效果,只不过编译器选项对项目中的所有文件都有效。 符号在源文件中保持已定义状态,直到源文件中的 #undef 指令删除该定义。 当你使用 -define 选项时,一个文件中的 #undef 指令不影响项目中的其他源代码文件。 可以将由此选项创建的符号同 #if#else#elif#endif 一起使用,对源文件进行条件编译。 C# 编译器本身不定义源代码中使用的符号或宏;所有符号定义必须都是用户定义的。

注意

C# #define 指令不允许符号具有值,如 C++ 等语言。 例如, #define 无法创建宏或定义常量。 如果需要定义一个常数,请使用 enum 变量。 如果要创建 C++样式的宏,请考虑使用泛型等替代项。 由于宏非常容易出错,所以 C# 不允许使用宏,但提供了更安全的替代项。

LangVersion

C# 编译器的默认语言版本依赖于应用程序的目标框架以及所安装的 SDK 或 Visual Studio 的版本。 这些规则是在 C# 语言版本控制中定义的。

警告

不要将 LangVersion 元素设置为 latest. latest 设置意味着已安装的编译器将使用其最新版本。 该版本可能会从计算机更改为计算机,使生成不可靠。 此外,它还支持可能需要当前 SDK 中不包含的运行时或库功能的语言功能。

LangVersion 选项使编译器仅接受指定 C# 语言规范中包含的语法,例如:

<LangVersion>9.0</LangVersion>

除了其他预览功能,某些预览功能还需要单独的选择加入 <LangVersion>preview</LangVersion>。 例如,C# 15 更新的内存安全规则使用 updated-memory-safety-rules 编译器功能。 有关详细信息,请参阅 “启用更新的内存安全规则”。

以下为有效值:

Value 含义
preview 编译器接受最新预览版中的所有有效语言语法。
latest 编译器接受最新发布的编译器版本(包括次要版本)中的语法。
latestMajor
default
编译器接受最新发布的编译器主要版本中的语法。
15.0 编译器仅接受 C# 15 或更低版本中包含的语法。
14.0 编译器仅接受 C# 14 或更低版本中包含的语法。
13.0 编译器只接受 C# 13 或更低版本中所含的语法。
12.0 编译器只接受 C# 12 或更低版本中所含的语法。
11.0 编译器只接受 C# 11 或更低版本中包含的语法。
10.0 编译器只接受 C# 10 或更低版本中所含的语法。
9.0 编译器只接受 C# 9 或更低版本中所含的语法。
8.0 编译器只接受 C# 8.0 或更低版本中所含的语法。
7.3 编译器只接受 C# 7.3 或更低版本中所含的语法。
7.2 编译器只接受 C# 7.2 或更低版本中所含的语法。
7.1 编译器只接受 C# 7.1 或更低版本中所含的语法。
7 编译器只接受 C# 7.0 或更低版本中所含的语法。
6 编译器只接受 C# 6.0 或更低版本中所含的语法。
5 编译器只接受 C# 5.0 或更低版本中所含的语法。
4 编译器只接受 C# 4.0 或更低版本中所含的语法。
3 编译器只接受 C# 3.0 或更低版本中所含的语法。
ISO-2
2
编译器只接受 ISO/IEC 23270:2006 C# (2.0) 中所含的语法。
ISO-1
1
编译器只接受 ISO/IEC 23270:2003 C# (1.0/1.2) 中所含的语法。

注意事项

  • 若要确保项目使用为目标框架推荐的默认编译器版本,请不要使用 LangVersion 选项。 更新目标框架以访问较新的语言功能。

  • 使用 值指定 default 与省略 LangVersion 选项不同。 指定 default 会使用编译器支持的语言的最新版本,而不考虑目标框架。 例如,如果未指定 LangVersion,则通过 Visual Studio 版本 17.6 生成面向 .NET 6 的项目将使用 C# 10,但如果 LangVersion 设置为 default,则使用 C# 11。

  • LangVersion 编译器选项不会影响 C# 应用程序引用的元数据。

  • 每个版本的 C# 编译器都包含语言规范的扩展,因此 LangVersion 不提供早期版本编译器的同等功能。

  • 虽然 C# 版本更新通常与主要的 .NET 版本一致,但新的语法和功能不一定会绑定到该特定的 Framework 版本。 每个特定功能都有自己的最低.NET API 或公共语言运行时要求,这些要求可能允许它通过包括 NuGet 包或其他库在下层框架上运行。

  • 无论使用哪一项 LangVersion 设置,请使用当前版本的公共语言运行时来创建 .exe 或 .dll。 友元程序集和 ModuleAssemblyName 是一个例外,它们在 -langversion:ISO-1 下工作。

若要了解指定 C# 语言版本的其他方式,请参阅 C# 语言版本控制

有关如何以编程方式设置此编译器选项的信息,请参阅 LanguageVersion

C# 语言规范

Version 链接 说明
C# 8.0 和更高版本 下载 PDF C# 语言规范版本 7:.NET Foundation
C# 7.3 下载 PDF 标准 ECMA-334 第 7 版
C# 6.0 下载 PDF 标准 ECMA-334 第 6 版
C# 5.0 下载 PDF 标准 ECMA-334 第 5 版
C# 3.0 下载 DOC C# 语言规范版本 3.0:Microsoft Corporation
C# 2.0 下载 PDF 标准 ECMA-334 第 4 版
C# 1.2 下载 DOC 标准 ECMA-334 第 2 版
C# 1.0 下载 DOC 标准 ECMA-334 第 1 版

支持所有语言功能所需的最低 SDK 版本

下表列出了支持相应语言版本的 C# 编译器的 SDK 的最低版本:

C# 版本 最低 SDK 版本
C# 12 Microsoft Visual Studio/生成工具 2022,版本 17.8 或 .NET 8 SDK
C# 11 Microsoft Visual Studio/生成工具 2022,版本 17.4 或 .NET 7 SDK
C# 10 Microsoft Visual Studio/生成工具 2022 或 .NET 6 SDK
C# 9.0 Microsoft Visual Studio/生成工具 2019 版本 16.8 或 .NET 5 SDK
C# 8.0 Microsoft Visual Studio/生成工具 2019,版本 16.3 或 .NET Core 3.0 SDK
C# 7.3 Microsoft Visual Studio/生成工具 2017,版本 15.7
C# 7.2 Microsoft Visual Studio/生成工具 2017,版本 15.5
C# 7.1 Microsoft Visual Studio/生成工具 2017,版本 15.3
C# 7.0 Microsoft Visual Studio/生成工具 2017
C# 6 Microsoft Visual Studio/生成工具 2015
C# 5 Microsoft Visual Studio/生成工具 2012 或捆绑的 .NET Framework 4.5 编译器
C# 4 Microsoft Visual Studio/生成工具 2010 或捆绑的 .NET Framework 4.0 编译器
C# 3 Microsoft Visual Studio/生成工具 2008 或捆绑的 .NET Framework 3.5 编译器
C# 2 Microsoft Visual Studio/生成工具 2005 或捆绑的 .Net Framework 2.0 编译器
C# 1.0/1.2 Microsoft Visual Studio/生成工具 .NET 2002 或捆绑的 .NET Framework 1.0 编译器

Nullable

使用 Nullable 选项指定可为 null 的上下文。 使用 <Nullable> 标记在项目的配置中设置它:

<Nullable>enable</Nullable>

参数必须为以下项之一:enabledisablewarningsannotations。 该 enable 参数打开可为 null 的上下文。 该 disable 参数关闭可为 null 的上下文。 该 warnings 参数打开可为 null 的警告上下文。 该 annotations 参数打开可为 null 的批注上下文。 有关这些值的详细信息,请参阅 可以为 Null 的上下文。 若要详细了解如何在现有代码库中启用可为 null 引用类型,请参阅 可为 null 的迁移策略

注意

如果未设置值,则默认值为 disable。 但是,.NET 6 和较新的模板默认将可为 Null 值设置为 enable Null。

流分析推断可执行代码中变量的可为 null 性。 推断出的变量的为空性与变量声明的为空性无关。 即使从编译的输出中有条件地省略调用,编译器也会分析方法调用。 例如,即使调用是有条件的,也不会编译为发布版本,编译器仍会分析对 Debug.Assert 空性的调用。

使用以下属性批注的方法的调用也会影响流分析:

重要

全局可为 null 上下文不适用于生成的代码文件。 无论此设置如何,都会针对标记为“已生成”的任何源文件禁用可为空上下文。 文件以下列方式之一标记为生成:

  1. 在 .editorconfig 中,在应用于该文件的部分中指定 generated_code = true
  2. 在文件顶部包含 <auto-generated><auto-generated/> 包含在注释中。 可以在批注中的任何一行上放置它,但注释块必须是文件中的第一个元素。
  3. 文件名以 TemporaryGeneratedFile_ 开头
  4. 文件名用以 .designer.cs.generated.cs.g.cs.g.i.cs 结尾。

生成器可以使用预处理器指令选择加入 #nullable