How to set .NET Core in #if statement for compilation
Asked Answered
D

5

66

I created a multi-targeted framework project. I use something like this:

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

But I can't find a wildcard for .NET Core. I tried:

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

But it is not valid statement.

Deliladelilah answered 20/7, 2016 at 9:0 Comment(3)
Change to #if NETCOREAPP1_0Haemin
Yes, replace . with _Hyson
Here msdn lists the predefined .net core symbols.Tonyatonye
J
94

You need an underscore, _, instead of a point:

NETCOREAPP1_0 or the more recent NETCOREAPP1_1 and NETCOREAPP2_0

The documentation for Target frameworks in SDK-style projects includes a list for the different preprocessor symbols.

.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+ and .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

For Mono you can usually use the NetFramework monikers known by your version of Mono. For instance, Mono 6.12 includes all NetFramework versions from 2.0 to 4.8. But if you must recognise Mono per se, then MONO and __MonoCS__ should both be defined.

Jonathonjonati answered 20/7, 2016 at 12:42 Comment(2)
You can define NETCOREAPP and NETSTANDARD without its version. I test it and It works in VS2019.Cassimere
For .NET 5 it NET5_0 learn.microsoft.com/en-us/dotnet/standard/frameworksChickabiddy
H
38

Extension of Devon's answer for Visual Studio 2017 .csproj files:

Looking at the table here, you can easily define constants by using regular expressions. So you don't need to think about updating the conditions if target frameworks are added/changed.

<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>

Usage:

#if NETFRAMEWORK
    FrameworkSpecific();
#endif

#if NETSTANDARD
    StandardSpecific();
#endif

#if NETCORE
    CoreSpecific();
#endif
Hersh answered 5/6, 2018 at 15:39 Comment(4)
good idea; it is a shame that these NETFRAMEWORK / NETSTANDARD / NETCORE symbols are not available as a standard part of the compilerTramel
you should primarily write code that runs everywhere, without relying on compiler flags. this approach is only there for the rare case you really need it.Jennijennica
@Tramel Seems like they are now (except the symbol for .NET Core is called NETCOREAPP)Porta
I think this ([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '^net\d'))) statement give wrong result for .net5.0 and .net 6.0Bully
R
13

You can define any custom conditional compilation symbols in the following way (project.json):

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

    }
}

This approach seems to be more practical because you may use the same conditional symbol for several targets, without need to write something like

#if NET20 && NET 40 && NET45
Runesmith answered 20/7, 2016 at 13:3 Comment(2)
where do you define the .net standard projects? Can you update your answer to show using multiple targetsBespatter
At the time this was posted, it was correct. But MS has moved away from project.json files to .csproj files. learn.microsoft.com/en-us/dotnet/core/migrationLapsus
S
7

For the new Visual Studio 2017 .csproj project system, you can find the full list of available symbols in Developing Libraries with Cross Platform Tools, How to Multitarget.

You can create composite constant(s) for it in your .csproj file like so:

  <PropertyGroup Condition="'$(TargetFramework)' == 'net451' Or '$(TargetFramework)' == 'net461' ">
    <DefineConstants>FULLFRAMEWORK;FULL</DefineConstants>
  </PropertyGroup>

Then you can use it in a #if compiler directive like so:

#if FULLFRAMEWORK
        private bool DoSomethingFullFrameworkSpecific()
        {
            var connectionStringSetting = ConfigurationManager.ConnectionStrings[connectionStringName];
            return connectionStringSetting != null;
        }
#endif
Simmonds answered 30/8, 2017 at 14:51 Comment(0)
A
2

While Vitaliy Fedorchenko's answer is correct, it should be noted that there is a bug in the .NET Core xproj project type. When you define a conditional compilation symbol through the project settings, it defines the element as "defines", but this is incorrect. It should create an element called "define". You can work around the issue by editing the project.json file manually.

I have logged this bug with Microsoft in two places. Please take the time to register your annoyance with Microsoft so that they eventually get around to fixing it and not causing this grief for others.

This thread has a detailed explanation of the problem with steps to reproduce, and screenshots:

3 Issues with NET Core Visual Studio Projects #4022

This is the Microsoft Connect bug report:

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

Afroamerican answered 10/8, 2016 at 23:48 Comment(2)
Microsoft has stopped the support for xproj and project.json in Vs2017Elanorelapid
The second link is (effectively) broken: "Microsoft Connect Has Been Retired". In any case, perhaps it is time for an update? (Note: the result should not be littered with "Edit:" or "Update: " (historical account of the answer itself), but as if the answer was written today, like "Until version this of that it had problem X, and it was fixed 2018-01-31 in version ExtraGood. In Visual Studio 2017, this was replaced with Y.")Ammonate

© 2022 - 2024 — McMap. All rights reserved.