Is it possible to conditionally compile to .NET Framework version?

c# conditional compilation
c# preprocessor directives
.net core framework version
targetframeworkversion
.net core if debug
c# if debug
c# define
how to target .net standard

I can recall back when working with MFC you could support multiple versions of the MFC framework by checking the _MFC_VER macro.

I'm doing some stuff now with .NET 4 and would like to use Tuple in a couple of spots but still keep everything else 3.5 compatible.

I'm looking to do something like:

#if DOTNET4
    public Tuple<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#else
    public KeyValuePair<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#endif

There are no builtin precompiler constants that you can use. But, it is easy enough create your own build configurations in VS with each configuration having its own set of defined constants and of course a target framework version. A lot of people do this to conditionally compile based 32 or 64 bit differences.

Conditional Compilation according to .NET Framework version, Are there any ways to make conditional compilation possible according to the . NET Framework version used? I guess this has to be achieved� One way is to tell msbuild to reference the library, conditional on the version of the.NET framework – and also, define a constant which can be used within the source code to choose the algorithm. In msbuild, define a constant according to the framework

There is one big caveat to be aware of when defining custom compilation symbols in your .csproj (or .vbproj, theoretically): they overwrite all previously-defined compilation symbols. For example, consider MSBuild snippet:

  <PropertyGroup Condition="'$(TargetFrameworkVersion)' == 'v4.0'">
    <DefineConstants>$(DefineConstants);DOTNET_40</DefineConstants>
  </PropertyGroup>
  <PropertyGroup>
    <DefineConstants>ITS_CLOBBERING_TIME</DefineConstants>
  </PropertyGroup>

The second DefineConstants element will, as its value suggests, clobber the first value of DefineConstants. To avoid this, you'll want to rewrite the second DefineConstants element to look like this:

    <DefineConstants>$(DefineConstants);ITS_CLOBBERING_TIME</DefineConstants>

Also, you'll want to place this inside of a PropertyGroup defined after all other PropertyGroups, as Visual Studio 2010 currently adds in custom compilation symbols in such a way that it will clobber any other custom compilation symbols you define if they are placed before Visual Studio plops down its definition. I've filed this issue with Microsoft. You can track its progress at Microsoft Connect.

#if preprocessor directive, When the C# compiler encounters an #if directive, followed eventually by WriteLine("Debug version"); #endif A conditional directive beginning with a #if directive must explicitly be The following example shows you how to test for different target frameworks so you can use newer APIs when possible:. I want to include stuff like Moth.Linq and ExtensionAttribute in .net 2.0 compilations, but exclude them from .net 3.5 compilations. In effect, I want to cross compile to .net 2.0 and .net 3.5. Not only do I want to do this from within Visual Studio, I also want the Continuous Integration server to do it too.

On a side note, your conditional compilation code will frustrate programmers that encounter it.

Edited, based on comments

It's probably better to write your own class so you can guarantee what it's going to do, and you don't have any weird signature or inheritance issues:

public class Pair<TSource, TResult>
{
    public TSource Source { get; set; }
    public TResult Result { get; set; }

    public Pair() {}
    public Pair(TSource source, TResult result)
    {
        Source = source;
        Result = result;
    }

    // Perhaps override Equals() and GetHashCode() as well
}

As always, it's good to weigh using the built-in stuff vs. rolling out your own code. Generally that means asking yourself, "Am I OK maintaining and supporting this code?" vs. "Does the code do what I need it to, out of the box?"

In this case, since you're not guaranteed to have Tuple<T1, T2>, I'd just write your own simple one so other developers can breathe easy :)

Conditional Compile based on .net framework version, Conditional Compile based on .net framework version Linq and ExtensionAttribute in .net 2.0 compilations, but exclude them from .net 3.5 That's likely incredibly fragile though – add a project and you tank that convention . After re-targetting the solution to .NET Framework 4.6, everything runs as expected and the user gets no prompts. Moral of the story is to always check which .NET version is installed before running tools that leverage the framework. This is also handy as a quick reference to see which versions are default on different versions of Windows.

As you should have different projects, you could have partial classes and only reference the one you need for each project with the specific logic for them:

classname.cs public partial classname { ... }

classname.40.cs public partial classname { public Tuple SomeMethod(){...} }

classname.35.cs public partial classname { public KeyValuePair SomeMethod(){...} }

msbuild: Compiling an Application against Different Versions of , A Windows service must be able connect to CRM systems of version 2011 or newer. This is an optional step and may be used for conditional compile. However NET Framework 4.0 version, which is used by default for the� You can implement your classes using a common feature set found in legacy and newer framework versions, but take advantage of useful features present in each version. This is possible using conditional compilation and compilation symbols, since you can define specific code to be compiled depending on target framework version (check this question: Is it possible to conditionally compile to .NET Framework version?

If you are using the .NET Core build system, you can use its predefined symbols:

#if NET40
    public Tuple<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#else
    public KeyValuePair<TSource, TResult> SomeMethod<TSource, TResult>(){...}
#endif

The list of predefined symbols is documented in Developing Libraries with Cross Platform Tools and #if (C# Reference):

.NET Framework: NETFRAMEWORK, NET20, NET35, NET40, NET45, NET451, NET452, NET46, NET461, NET462, NET47, NET471, NET472, NET48

.NET Standard: NETSTANDARD, NETSTANDARD1_0, NETSTANDARD1_1, NETSTANDARD1_2, NETSTANDARD1_3, NETSTANDARD1_4, NETSTANDARD1_5, NETSTANDARD1_6, NETSTANDARD2_0, NETSTANDARD2_1

.NET Core: NETCOREAPP, NETCOREAPP1_0, NETCOREAPP1_1, NETCOREAPP2_0, NETCOREAPP2_1, NETCOREAPP2_2, NETCOREAPP3_0

Multi-targetting .Net Framework and .Net Core in a single project , Learn about conditional sections in your csproj file, so that you can declare language features such as async/await for which the C# compiler relies on access to . Polyfills are sometimes possible. framework classes and methods not NET.Test.Sdk" Version = "15.8.0" />. < PackageReference Include� For example, CLR version 4.0.30319.xxxxx where xxxxx is less than 42000, supports .NET Framework versions 4 through 4.5.2. CLR version greater than or equal to 4.0.30319.42000 supports .NET Framework versions starting with .NET Framework 4.6. Community-maintained tools are available to help detect which .NET Framework versions are installed:

Platform Conditional Compilation in .NET Core, If you want to perform this check at compile time in order to build certain parts of your code only TargetFramework >netcoreapp2.0</ TargetFramework > Docker for Windows you should be able to run Docker commands from a command prompt. NET or OS version or a specific deployment scenario. If certain projects do not support both versions, you can uncheck them before clicking on Close button. This is usually done, when your solution has 2 parts – API and Server and you want the API to be multi-framework target and Server code to run on a particular version of .NET Step 2 – Framework Targeting in Projects

How to conditionally compile against different .NET framework , NET 4.0 consumers (the later framework version allows parallel execution using Specify conditional compilation directives in the source code� conditional compilation based on the framework version? The idea is to be able to compile the "same" code for both the 1.0 frameworkand the 1.1 framework, something like #If "Framework 1.0 etected" then DO NOT USE SOME FUNCTION (as it uses some 1.1 only properties of certainclasses) else BUILD FOR 1.1 p.s. To be more specific it's the Fields property of the

<PackageReference> System.* when targeting NET Framework , NET Framework 4.5 is different than all the later framework versions as the type forwarding facade actually Library that we reference to prevent it being allowed . NET Core and don't have code conditionally compiled for .

Comments
  • Perhaps vote up this: connect.microsoft.com/VisualStudio/feedback/details/679124/…
  • possible duplicate of Conditional Compilation and Framework Targets
  • This user voice is not quite the same and anyways is closed. I couldn't find any other that speaks to framework version so I created one, visualstudio.uservoice.com/forums/121579-visual-studio/…. Please upvote it.
  • I wonder why they don't build these in like they do DEBUG and CODE_ANALYSIS.
  • dkackman: Eric Lippert always says that these features don't build themselves; the feature does not exist simply because nobody ever designed, specified, implemented, tested, documented and shipped that feature. See blogs.msdn.com/ericlippert/archive/2009/06/22/…
  • A build-configuration does not cover Platform and Referenced Assemblies. You will have to configure a different Project for each platform.
  • @configurator: Fair point. It just seems like a logical thing to do for the most common non-build configuration sorts of things (i.e. things that have to be handled at the project level and is a pattern that is already part of vs.net. A compact framework project defines PocketPC automatically for instance.
  • @dkackman: I don't think DEBUG and CODE_ANALYSIS are build in, at least there not automatically defined if you compile with debug or so. For example: DEBUG is explicitly set in the csproj (i.e. msbuild file) when you run the "Debug" configuration.
  • You don't even need to do this conditionally, you could just define: <DefineConstants>NETFX$(TargetFrameworkVersion.Replace("v", "").Replace(".", "_"));$(DefineConstants)</DefineConstants>
  • Isn't KeyValuePair<TKey, TValue> a struct?