Skip to content

Instantly share code, notes, and snippets.

@Chasmical
Last active August 20, 2023 19:28
Show Gist options
  • Save Chasmical/fb334fb3ddcdb35720df862d85723ca4 to your computer and use it in GitHub Desktop.
Save Chasmical/fb334fb3ddcdb35720df862d85723ca4 to your computer and use it in GitHub Desktop.
Define OR_GREATER for .NET Standard versions when targeting .NET Core/Framework

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment