Overview of Polyfill
mainnetstandard2.0 and provides a wide range of APIs across various frameworks, including .NET Framework, .NET Core, .NET 5+, and UWP.repository·main·Indexed 19 days ago
https://github.com/simoncropp/polyfillA source-only package that provides newer .NET and C# features to older runtimes, targeting netstandard2.0. It enables modern syntax and APIs—including Index and Range syntax, required members, and various attributes (ModuleInitializer, IsExternalInit, CallerArgumentExpression)—across .NET Framework, .NET Core, .NET 5+, and UWP. It also provides extension methods for ArgumentException, ArraySegment<T>, Base64, and BinaryPrimitives, as well as missing members for CancellationToken and concurrent collections.
netstandard2.0 and provides a wide range of APIs across various frameworks, including .NET Framework, .NET Core, .NET 5+, and UWP.Polyfill provides several mechanisms to bridge the gap between runtime versions:
Ensure, Guard, Nullability, ArgumentExceptions, and StringInterpolation.Due to breaking changes in C# 14/dotnet 10 regarding how array.Reverse() is resolved (shifting from Enumerable.Reverse to an in-place Span reversal), this package includes a polyfill for the Enumerable.Reverse<T>(this T[]) overload on older target frameworks.
This polyfill is located in the System.Linq namespace to ensure it takes precedence over Polyfills (which is available via global using) when resolving extension methods from using System;.
Failure to multi-target when using Polyfill results in three main negative impacts:
StringBuilder.Append(ReadOnlySpan<char>) on netcore2 performs a ToString() call, which causes an unnecessary string allocation.net10 to ~230 KB on net461 if it is not properly multi-targeted.By default, all Polyfill types are marked as internal. This allows the package to be used across multiple projects without causing type name conflicts.
If your projects use InternalsVisibleTo (e.g., for unit testing), you may encounter type visibility conflicts. To resolve this, use the Embedded pattern: use the Polyfill source package and set <PolyUseEmbeddedAttribute>true</PolyUseEmbeddedAttribute> in a <PropertyGroup>. This ensures that the types are treated as truly embedded and remain invisible to other assemblies even when InternalsVisibleTo is present.
<PropertyGroup>
<PolyUseEmbeddedAttribute>true</PolyUseEmbeddedAttribute>
</PropertyGroup>You can consume Polyfill through NuGet. There are two packages available:
Polyfill: The standard source-only package.PolyfillLib: A library version of the package (refer to the PolyfillLib documentation for specific usage).Package links:
To ensure compatibility with the features used by Polyfill, it is recommended to use a recent SDK via a global.json file.
{
"sdk": {
"version": "10.0.300",
"rollForward": "latestFeature"
}
}When working in a solution that produces an application, the recommended approach is to add the Polyfill NuGet package only to the root app project and enable the PolyPublic property.
By setting <PolyPublic>true</PolyPublic>, the polyfills become available to all downstream projects in the solution (such as test projects) without requiring them to reference the Polyfill NuGet package directly.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PolyPublic>true</PolyPublic>
</PropertyGroup>
</Project>Polyfill is a source-only package that provides newer .NET and C# features to older runtimes. Because it is source-only, it compiles directly into your consuming project and does not create a runtime dependency.
To use it, add the Polyfill package to your project. It is recommended to set your <LangVersion> to latest to take advantage of the newer C# features being polyfilled.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Polyfill" Version="*" PrivateAssets="all" />
</ItemGroup>
</Project>To enable support for custom interpolated string handlers (like AppendInterpolatedStringHandler and DefaultInterpolatedStringHandler), add the PolyStringInterpolation property to your MSBuild project file:
<PropertyGroup>
<PolyStringInterpolation>true</PolyStringInterpolation>
</PropertyGroup>There are two ways to consume Polyfill when building a library:
InternalsVisibleTo to expose APIs, you can add the Polyfill NuGet package to all individual projects in your solution.InternalsVisibleTo: If you use InternalsVisibleTo (for example, to expose internal APIs to a test project), you should add the Polyfill NuGet package only to the root library project to avoid visibility issues.Certain polyfills require specific NuGet packages to be present in your project. If these references are missing, the related polyfills will be disabled.
Required if targeting net461 or net462.
Required if using Span APIs and targeting netstandard, netframework, or netcoreapp2*.
Warning: If System.Memory is installed at a version older than 4.5.5, a build warning PolyfillMemoryVersion will be raised. Older versions lack the types required for FeatureMemory to be enabled, which can cause polyfills to fail silently.
Required if using ValueTask APIs and targeting netframework, netstandard2, or netcoreapp2.
Required if using RuntimeInformation or OSPlatform and targeting netframework.
<!-- System.ValueTuple -->
<PackageReference Include="System.ValueTuple" Version="4.5.0" Condition="$(TargetFramework.StartsWith('net46'))" />
<!-- System.Memory -->
<PackageReference Include="System.Memory" Version="4.5.5" Condition="$(TargetFrameworkIdentifier) == '.NETStandard' or $(TargetFrameworkIdentifier) == '.NETFramework' or $(TargetFramework.StartsWith('netcoreapp2'))" />
<!-- System.Threading.Tasks.Extensions -->
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" Condition="$(TargetFramework) == 'netstandard2.0' or $(TargetFramework) == 'netcoreapp2.0' or $(TargetFrameworkIdentifier) == '.NETFramework'" />
<!-- System.Runtime.InteropServices.RuntimeInformation -->
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" Condition="$(TargetFrameworkIdentifier) == '.NETFramework'" />