This repository demonstrates how to provide polyfill support for C# 9.0+ features (such as record, init-only setter, Index/Range, etc.) in legacy .NET environments like .NET Framework 4.8.
Polyfill.Example.slnx
src/
Polyfill.Example.IndexRange/ // Index/Range feature demo
Program.cs
...
Polyfill.Example.IsExternalInit/ // isExternalInit feature demo
Program.cs
...
C# 9.0 introduces features like record types and init accessors, but these require .NET 5+ runtime support. In older versions such as .NET Framework 4.8, the lack of System.Runtime.CompilerServices.IsExternalInit causes compilation errors. This project demonstrates how to add custom types and code to enable compatibility with these new features.
Polyfill.Example.IsExternalInit: Shows how to provide theIsExternalInittype for .NET Framework to supportinitsetters andrecord.Polyfill.Example.IndexRange: Demonstrates using C# 8.0 Index/Range syntax in legacy .NET environments.
git clone https://github.com/yourname/Polyfill.Example.IsExternalInit.git
cd Polyfill.Example.IsExternalInitFor Polyfill.Example.IsExternalInit:
cd src/Polyfill.Example.IsExternalInit
msbuild /p:Configuration=Debug
bin\Debug\net48\Polyfill.Example.IsExternalInit.exeFor Polyfill.Example.IndexRange:
cd src/Polyfill.Example.IndexRange
msbuild /p:Configuration=Debug
bin\Debug\net48\Polyfill.Example.IndexRange.exesrc/Polyfill.Example.IsExternalInit/Program.cs:
// Polyfill for IsExternalInit (only needed for legacy .NET)
namespace System.Runtime.CompilerServices
{
public class IsExternalInit { }
}
public record Person(string Name) { public int Age { get; init; } }
class Program
{
static void Main()
{
var p = new Person("Zhang San") { Age = 18 };
Console.WriteLine($"{p.Name}, {p.Age}");
}
}Output:
Zhang San, 18
src/Polyfill.Example.IndexRange/Program.cs:
class Program
{
static void Main()
{
int[] arr = { 1, 2, 3, 4, 5 };
// Use Index/Range syntax
int last = arr[^1]; // 5
int[] sub = arr[1..^1]; // {2,3,4}
Console.WriteLine(last);
Console.WriteLine(string.Join(",", sub));
}
}Output:
5
2,3,4