So, I had this code that I wanted to work properly:
namespace AbbLab.Compatibility
{
public static class Shims
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T[] Empty<T>()
#if NETSTANDARD1_3_OR_GREATER
=> System.Array.Empty<T>();
#else
=> EmptyArray<T>.Instance;
private static class EmptyArray<T>
{
internal static readonly T[] Instance = new T[0];
}
#endif
}
}
But when targeting .NET 5.0, I noticed that NETSTANDARD1_3_OR_GREATER
was not defined for some reason, even though .NET 5.0 implements .NET Standard 2.1. I spent several days trying to figure out what's wrong with my .NET SDK's installation. Turns out, everything's working as intended - .NET Core was never supposed to have OR_GREATER symbols of .NET Standard. So I spent a day digging in MSBuild's docs and files, and invented a work-around:
<Project>
<!-- This is the Directory.Build.props file, in the root of your solution -->
<PropertyGroup Condition="'$(TargetFramework)' != '' and ('$(TargetFrameworkIdentifier)' == '' or '$(TargetFrameworkVersion)' == '')">
<TargetFrameworkIdentifier>$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)'))</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)', 2))</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<!-- .NET Core 1.0+ implements .NET Standard 1.0 through 1.6 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '1.0'))">$(DefineConstants);NETSTANDARD1_0_OR_GREATER;NETSTANDARD1_1_OR_GREATER;NETSTANDARD1_2_OR_GREATER;NETSTANDARD1_3_OR_GREATER;NETSTANDARD1_4_OR_GREATER;NETSTANDARD1_5_OR_GREATER;NETSTANDARD1_6_OR_GREATER</DefineConstants>
<!-- .NET Core 2.0+ implements .NET Standard 2.0 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '2.0'))">$(DefineConstants);NETSTANDARD2_0_OR_GREATER</DefineConstants>
<!-- .NET Core 3.0+ implements .NET Standard 2.1 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.0'))">$(DefineConstants);NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<!-- .NET Framework 4.5+ implements .NET Standard 1.0 through 1.1 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '4.5'))">$(DefineConstants);NETSTANDARD1_0_OR_GREATER;NETSTANDARD1_1_OR_GREATER</DefineConstants>
<!-- .NET Framework 4.5.1+ implements .NET Standard 1.2 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '4.5.1'))">$(DefineConstants);NETSTANDARD1_2_OR_GREATER</DefineConstants>
<!-- .NET Framework 4.6+ implements .NET Standard 1.3 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '4.6'))">$(DefineConstants);NETSTANDARD1_3_OR_GREATER</DefineConstants>
<!-- .NET Framework 4.6.1+ implements .NET Standard 1.4 through 2.0 -->
<DefineConstants Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '4.6.1'))">$(DefineConstants);NETSTANDARD1_4_OR_GREATER;NETSTANDARD1_5_OR_GREATER;NETSTANDARD1_6_OR_GREATER;NETSTANDARD2_0_OR_GREATER</DefineConstants>
</PropertyGroup>
</Project>
With this, NETSTANDARDX_Y_OR_GREATER
will be defined for versions of Core and Framework that implement those standards.