如何在#if语句中设置.NET Core以进行编译

62

我创建了一个多目标框架项目。我使用类似这样的东西:

  #if NET40
    Console.WriteLine("Hello from .NET Core 4");
  #endif

但我找不到.NET Core的通配符。我尝试过:

   #if NETCOREAPP1.0
     Console.WriteLine("Hello from .NET Core");
   #endif

但这句话并不是有效的陈述。


4
改为 #if NETCOREAPP1_0 - Kiran
1
是的,请用下划线 _ 替换 . - MartinHN
1
在这里,MSDN 列出了预定义的 .NET Core 符号。 - Veverke
5个回答

89
您需要使用下划线_代替点号:

NETCOREAPP1_0 或更近期的 NETCOREAPP1_1NETCOREAPP2_0

SDK 风格项目中的目标框架文档列出了不同预处理器符号的列表。

.NET Framework

NETFRAMEWORK, NET48, NET472, NET471, NET47, NET462, NET461, NET46, NET452, NET451, NET45, NET40, NET35, NET20

.NET Standard

NETSTANDARD, NETSTANDARD2_1, NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2, NETSTANDARD1_1, NETSTANDARD1_0

.NET 5+ 和 .NET Core

NET, NET6_0, NET6_0_ANDROID, NET6_0_IOS, NET6_0_MACOS, NET6_0_MACCATALYST, NET6_0_TVOS, NET6_0_WINDOWS, NET5_0, NETCOREAPP, NETCOREAPP3_1, NETCOREAPP3_0, NETCOREAPP2_2, NETCOREAPP2_1, NETCOREAPP2_0, NETCOREAPP1_1, NETCOREAPP1_0

Mono

对于 Mono,您通常可以使用您的版本已知的 NetFramework 版本。例如,Mono 6.12 包括从 2.0 到 4.8 的所有 NetFramework 版本。但是,如果您必须识别 Mono 本身,则应定义 MONO__MonoCS__


4
您可以定义NETCOREAPPNETSTANDARD而无需指定其版本号。我测试过,在VS2019中可以正常工作。 - Mahdi Ataollahi
对于.NET 5,它是“NET5_0”。https://learn.microsoft.com/en-us/dotnet/standard/frameworks - ruslanen

38

对于Visual Studio 2017的.csproj文件拓展自Devon的回答

查看这里的表格,你可以通过正则表达式轻松定义常量。因此,如果添加/更改目标框架,您无需考虑更新条件。

<PropertyGroup Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '^net\d'))">
  <DefineConstants>NETFRAMEWORK</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '^netstandard\d'))">
  <DefineConstants>NETSTANDARD</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '^netcoreapp\d'))">
  <DefineConstants>NETCORE</DefineConstants>
</PropertyGroup>

使用说明:

#if NETFRAMEWORK
    FrameworkSpecific();
#endif

#if NETSTANDARD
    StandardSpecific();
#endif

#if NETCORE
    CoreSpecific();
#endif

6
好主意;可惜这些NETFRAMEWORK / NETSTANDARD / NETCORE符号不作为编译器的标准部分提供。 - gallivantor
2
你应该编写能够在任何地方运行的代码,而不依赖于编译器标志。这种方法只适用于你真正需要的罕见情况。 - MovGP0
8
看起来它们现在是这样(除了.NET Core符号被称为NETCOREAPP)。 - FunctorSalad
我认为这个语句 ([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '^net\d'))) 对于 .net5.0 和 .net 6.0 给出了错误的结果。 - captainblack

13

您可以按照以下方式(project.json)定义任何自定义条件编译符号:

"frameworks": {
    "net40": {
      "buildOptions": {
        "define": ["NET_40"]
      }
    },
    "netstandard1.5": {
      "buildOptions": {
        "define": [ "NET_STANDARD" ]
      }

    }
}

这种方法似乎更实用,因为您可以针对多个目标使用相同的条件符号,而无需编写类似以下的内容:

这种方法看起来更切实可行,因为您可以使用同一个条件符号来匹配多个目标,而不需要编写像以下这样的内容:

#if NET20 && NET 40 && NET45

1
你在哪里定义 .NET 标准项目?你能更新你的答案,展示如何使用多个目标吗? - H20rider
1
发布时,这是正确的。但是微软已经从project.json文件转向.csproj文件。https://learn.microsoft.com/en-us/dotnet/core/migration/ - Glenn

7
对于新的Visual Studio 2017 .csproj项目系统,您可以在使用跨平台工具开发库,如何多目标中找到可用符号的完整列表。
您可以在.csproj文件中创建复合常量,如下所示:
  <PropertyGroup Condition="'$(TargetFramework)' == 'net451' Or '$(TargetFramework)' == 'net461' ">
    <DefineConstants>FULLFRAMEWORK;FULL</DefineConstants>
  </PropertyGroup>

然后您可以在 #if 编译器指令中这样使用它:

#if FULLFRAMEWORK
        private bool DoSomethingFullFrameworkSpecific()
        {
            var connectionStringSetting = ConfigurationManager.ConnectionStrings[connectionStringName];
            return connectionStringSetting != null;
        }
#endif

2
虽然Vitaliy Fedorchenko's answer是正确的,但需要注意的是.NET Core xproj项目类型存在一个错误。当您通过项目设置定义条件编译符号时,它将元素定义为“定义”,但这是不正确的。它应该创建一个名为“define”的元素。您可以通过手动编辑project.json文件来解决此问题。
我在两个地方向微软记录了此错误。请花些时间向微软表达您的不满,以便他们最终解决它,不会给其他人带来麻烦。
本主题详细说明了问题,并提供了重现步骤和屏幕截图: NET Core Visual Studio Projects #4022存在3个问题 这是Microsoft Connect的错误报告:

https://connect.microsoft.com/VisualStudio/feedbackdetail/view/2983351/conditional-compilation-symbols-broken-in-net-core-projects#tabs


1
微软已经停止了Vs2017中xproj和project.json的支持。 - M.Hassan
第二个链接(实际上)已经失效: "Microsoft Connect Has Been Retired"。无论如何,也许现在是更新的时候了?(注意:结果不应该被“编辑:”或“更新:”这样的东西所淹没(回答本身的历史账户),而像是今天写的一样,“直到某个版本,它有问题X,在2018-01-31中已经解决,并在Visual Studio 2017中用Y替换。”) - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接