It's very easy to multitarget a library in the csproj. All you need to do is listing all target frameworks in the
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net5.0;netstandard2.1;netstandard2.0;net461</TargetFrameworks> </PropertyGroup> </Project>
Then, you may have different implementations in the code depending on the target framework. When MSBuild compiles your project it automatically adds a symbol you can use in
#if. For instance, you can use
#if NET461 ... #endif to compile a code specific to the net461 target.
#if NET461 // Code specific to net461 #elif NETSTANDARD2_0 || NETSTANDARD2_1 // Code specific to netstandard2.1 or netstandard2.0 #else // Code specific to other frameworks #endif
The pattern I often see in codebases is:
#if NET5_0 // Optimized code that uses .NET 5.0 API #else // Legacy implementation for previous frameworks #endif
This code is fine until you add new target frameworks. Indeed, you may want newer frameworks to use the optimal case, but it may end up using the legacy implementation case. Finding all
#if to update is error-prone. An easy way to prevent that is to add a
#else and report an error using
#if NET5_0 // Optimized code that uses .NET 5.0 API #elif NETSTANDARD2_0 || NETSTANDARD2_1 // Legacy implementation for previous frameworks #else // Prevent compilation for unknown target frameworks #error Target Framework not supported #endif
If you add a new target, you'll get a compilation error. Note that the error list window shows the target where the error is reported (
netcoreapp3.1 in this case).
You can now check all locations that need to be updated when adding a new TFM.
Future versions of .NET may provide
OR_GREATER preprocessor symbols for TFMs to create forward-compatible
#if. This should allow using preprocessor symbols such as
NET5_0_OR_GREATER. Here's a link to the accepted proposal "OR_GREATER preprocessor symbols for TFMs proposal"
Do you have a question or a suggestion about this post? Contact me!