4

I'm attempting to use an if compiler directive to conditionally include some code that is required for earlier versions of the .Net Framework, but not later versions.

I've used the following references from MSDN, the #if compiler directive reference, and the Target Frameworks reference.

I'm authoring a .Net 4.5.1 application, but the NET451 symbol doesn't appear to be defined, and neither do any others.

I've adapted the example from the Target Frameworks MSDN article to include all framework symbols, so I can see which one is defined.

#if NET20
        Console.WriteLine("Target framework: NET20");
#elif NET35
        Console.WriteLine("Target framework: NET35");
#elif NET40
        Console.WriteLine("Target framework: NET40");
#elif NET45
        Console.WriteLine("Target framework: NET45");
#elif NET451
        Console.WriteLine("Target framework: NET451");
#elif NET452
        Console.WriteLine("Target framework: NET452");
#elif NET46
        Console.WriteLine("Target framework: NET46");
#elif NET461
        Console.WriteLine("Target framework: NET461");
#elif NET462
        Console.WriteLine("Target framework: NET462");
#elif NET47
        Console.WriteLine("Target framework: NET47");
#elif NET471
        Console.WriteLine("Target framework: NET471");
#elif NET472
        Console.WriteLine("Target framework: NET472");
#elif NETSTANDARD1_0
        Console.WriteLine("Target framework: NETSTANDARD1_0");
#elif NETSTANDARD1_1
        Console.WriteLine("Target framework: NETSTANDARD1_1");
#elif NETSTANDARD1_2
        Console.WriteLine("Target framework: NETSTANDARD1_2");
#elif NETSTANDARD1_3
        Console.WriteLine("Target framework: NETSTANDARD1_3");
#elif NETSTANDARD1_4
        Console.WriteLine("Target framework: NETSTANDARD1_4");
#elif NETSTANDARD1_5
        Console.WriteLine("Target framework: NETSTANDARD1_5");
#elif NETSTANDARD1_6
        Console.WriteLine("Target framework: NETSTANDARD1_6");
#elif NETSTANDARD2_0
        Console.WriteLine("Target framework: NETSTANDARD2_0");
#elif NETCOREAPP1_0
        Console.WriteLine("Target framework: NETCOREAPP1_0");
#elif NETCOREAPP1_1
        Console.WriteLine("Target framework: NETCOREAPP1_1");
#elif NETCOREAPP2_0
        Console.WriteLine("Target framework: NETCOREAPP2_0");
#elif NETCOREAPP2_1
        Console.WriteLine("Target framework: NETCOREAPP2_1");
#elif NETCOREAPP2_2
        Console.WriteLine("Target framework: NETCOREAPP2_2");
#else
        Console.WriteLine("Could not tell which framework we're using.");
#endif

The resulting output is "Could not tell which framework we're using".

Am I doing something wrong? Is the documentation incorrect? Or have I found a bug?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Doctor Jones
  • 21,196
  • 13
  • 77
  • 99
  • 1
    Please could you give a sample project file? That will affect what symbols are defined. – Jon Skeet Feb 11 '19 at 11:24
  • How do you compile the code? Do you use Visual Studio (MSBuild), or do you run `csc.exe` from the command line? – CodeCaster Feb 11 '19 at 11:25
  • (I've just tried this from a brand new .NET Core style SDK project with `net451` and it was fine. – Jon Skeet Feb 11 '19 at 11:25
  • Not sure whether you did or not, but did you pay attention to the section titled "How to specify target frameworks" in the "Target frameworks" reference you linked to? –  Feb 11 '19 at 11:26
  • @CodeCaster, I'm using Visual Studio 2017, 15.9.6. – Doctor Jones Feb 11 '19 at 11:29
  • I'm using that as well, and a new Console Application targeting .NET Framework 4.7.1 exhibits the same behavior you describe. All code is greyed out except the "Could not tell[...]" line. – CodeCaster Feb 11 '19 at 11:31

1 Answers1

6

These directives are only implicitly generated by the build system for .NET Core. Keyword from the documentation:

The complete list of preprocessor symbols for .NET Core target frameworks is:

So when you create a new application or class library targeting .NET Framework, the directives will be missing. Instead create a Core or .NET Standard library or application.

If you're not ready to move to Core, see Detect target framework version at compile time for workarounds - you could define them yourself, for example.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • In my case, it's a WPF application, so I can't use .Net core, or the standard project format, yet. Thanks! – Doctor Jones Feb 11 '19 at 12:07
  • The current [#if documentation](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-if) pretty clearly suggests that symbols will be predefined for the various framework versions too, but I guess it is incorrect :[ – dlf Feb 22 '19 at 13:57
  • This [issue report](https://github.com/dotnet/docs/issues/7096) suggests it is a documentation error that will be fixed quite soon – dlf Feb 22 '19 at 14:02
  • 2
    @dlf, you can get the symbols to work with .Net Framework projects, but you must use the new .NetStandard project format, and target your preferred .NetFramework version. They even have an example on the documentation page. – Doctor Jones Feb 22 '19 at 16:30
  • I just opened a project targeting .NET Framework 4 and NET40 is very well defined because my #if NET40 are working correctly, when I change the target framework to .NET Framework 4.7.2 the #if NET472 is not working. I dont think NET40 has anything to do with .NET Core, otherwise why would be that one defined when targeting .NET Framework 4? – user1464603 Jun 10 '20 at 18:56