C#编译器csc.exe
和C#语言本身不会为conditional compilation公开任何预定义的常量。 VisualStudio
仅添加了可通过IDE配置的DEBUG
和TRACE
值。 IDE还允许您添加自己的任意符号,但由于这些符号基本上是固定的(不变的)值,因此该功能的使用受到限制。
更强大的自定义选项可以通过手动编辑您的.csproj
项目文件来设置。根据MSBuild(见here和here)提供的大量环境和配置信息,您可以在这里将conditions设置为selectively propagate以selectively propagate条件编译为C#,但原则上可能没有完整列表,因为不同组件会任意贡献元数据特设)。
让我们考虑一个工作示例。有条件编译有用的一种情况是,如果您想编写适合构建过程中发现的任何工具的代码。通过这种方式,您可以利用最新的语言功能,同时仍能够保留在具有较旧工具的机器上进行编译的能力,而这正如预期的那样会拒绝外来语法和/或关键字。对于C# 7.0在vs2017
特定的情况下,我们可以通过修改.csproj
如下:
.csproj的文件(节选):
您还可以识别每个上了年纪的C#编译器,以及,一路上优雅地退化。这同样适用于检测所述.NET Framework
版本(经常要求在计算器上[1] [2] [3] [4])和任何其它环境条件的构建。这些作为练习留给读者,但如果你想从上面复制/粘贴突出显示的行,这里是文本版本。由于在截屏的更新,我加了单引号的条件表达式这里(即使一切似乎没有他们的工作)
<DefineConstants Condition="'$(VisualStudioVersion)'=='15'">CSHARP7</DefineConstants>
<!-- ... -->
<DefineConstants>DEBUG;TRACE;$(DefineConstants)</DefineConstants>
<!-- ... -->
<DefineConstants>TRACE;$(DefineConstants)</DefineConstants>
不管怎么说,以这种方式,你现在就可以编写使用#if… #elif… #else… #endif
有条件的C#代码 。继续这个例子,下面的代码使用新的元组语法 - 只在C#7中可用 - 交换数组元素。顺便提一句,元组版本不仅更简洁和/或优雅,它也产生优异的IL代码:
#if CSHARP7
(rg[i], rg[j]) = (rg[j], rg[i]); // swap elements: tuple syntax
#else
var t = rg[i]; // swap elements: clunky
rg[i] = rg[j];
rg[j] = t;
#endif
注意,Visual Studio
IDE 确实正确处理您的人工.csproj
自定义在每一个方面。鉴于.csproj
我之前展示的IDE代码编辑器可以正确识别和评估为目的,条件编译IntelliSense
,refactoring
,“调出”的代码不激活块等
我也提到了MSBuild
有一个宝库的信息可用,其中$(VisualStudioVersion)
只是一个例子。不幸的是,不容易找出哪些值是可用的,以及它们在构建时可能具有的值。一个诀窍就是临时把C++
项目放到你的C#项目旁边的Visual Studio
解决方案中(如果你还没有的话)。如果您右键点击项目属性对于此.vcxproj
,然后查看(例如,)“附加包含目录”的C/C++
页面上,一个下拉菜单会出现在最右边,当您单击编辑:
你会得到一个对话框,以“宏”按钮,就可以单击以获取所有可用变量的列表以及根据当前在IDE中选择的平台和配置的预期值。请不要忽略列表底部的well-known-item-metadata字段(前缀为%
)。
你可以得到很多东西是如何在这里从这张截图的滚动条拇指大小的想法。 (它们按字母顺序排列,我只是滚动到“P”部分的这部分,因为它的个人信息很少)。然而,需要注意的是,在构建过程中,(可用)变量及其值随着时间的推移而变化,因此您可能会发现此列表中的项目在处理时不可用于您的.csproj
。
Awsome!这个答案需要更多的投票!特别是对于C++提示:-) – Matt 2017-05-12 13:16:16