akanse.GenericSpecializationGenerator
0.1.4
dotnet add package akanse.GenericSpecializationGenerator --version 0.1.4
NuGet\Install-Package akanse.GenericSpecializationGenerator -Version 0.1.4
<PackageReference Include="akanse.GenericSpecializationGenerator" Version="0.1.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="akanse.GenericSpecializationGenerator" Version="0.1.4" />
<PackageReference Include="akanse.GenericSpecializationGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add akanse.GenericSpecializationGenerator --version 0.1.4
#r "nuget: akanse.GenericSpecializationGenerator, 0.1.4"
#addin nuget:?package=akanse.GenericSpecializationGenerator&version=0.1.4
#tool nuget:?package=akanse.GenericSpecializationGenerator&version=0.1.4
GenericSpecializationGenerator
<img src="https://img.shields.io/badge/-GitHub-blue.svg?logo=github" />
<img src="https://img.shields.io/badge/-NuGet-019733.svg?logo=nuget" />
Provides generic type specialization.
What's this?
This is a source generator that achieves specialization of .Net generic methods, similar to template specialization in C++.
Considering the nature of JIT, it can generate source code with very low overhead, especially in release builds.
Usage
using GenericSpecialization.DebugApp;
partial class SampleInstanceClass
{
// Add `PrimaryGenericAttribute` to generic method declaration
// with a parameter of the method name which will be called for default code path.
[PrimaryGeneric(nameof(FooDefault))]
public partial void Foo<T>(T input);
// Define default implementation of target generic method.
private void FooDefault<T>(T input)
{
Console.WriteLine($"default");
}
// Write non-generic method which has same signature with the closed of target generic method declaration.
// They will be detected automatically and be treated as implementation of generic specialization.
private void Foo(int input)
{
Console.WriteLine($"int specialized");
}
private void Foo(double input)
{
Console.WriteLine($"double specialized");
}
// When derived types are included, the priority is determined based on the standard overload resolution order.
private static void Foo(List<double> input)
{
Console.WriteLine($"List<double> specialized");
}
private static void Foo(IList<double> input)
{
Console.WriteLine($"IList<double> specialized");
}
private static void Foo(IEnumerable<double> input)
{
Console.WriteLine($"IEnumerable<double> specialized");
}
}
Against the preceding code, this generator will generate such as following code:
// <auto-generated/>
#nullable enable
#pragma warning disable CS8600
#pragma warning disable CS8601
#pragma warning disable CS8602
#pragma warning disable CS8603
#pragma warning disable CS8604
using System.Runtime.CompilerServices;
namespace GenericSpecializationGenerator.DebugApp;
partial class SampleInstanceClass
{
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public partial void Foo<T>(T input)
{
if(typeof(T) == typeof(int))
{
var _input = Unsafe.As<T, int>(ref input);
Foo(_input);
return;
}
if(typeof(T) == typeof(double))
{
var _input = Unsafe.As<T, double>(ref input);
Foo(_input);
return;
}
if(typeof(System.Collections.Generic.List<double>).IsAssignableFrom(typeof(T)))
{
var _input = Unsafe.As<T, System.Collections.Generic.List<double>>(ref input);
Foo(_input);
return;
}
if(typeof(System.Collections.Generic.IList<double>).IsAssignableFrom(typeof(T)))
{
var _input = Unsafe.As<T, System.Collections.Generic.IList<double>>(ref input);
Foo(_input);
return;
}
if(typeof(System.Collections.Generic.IEnumerable<double>).IsAssignableFrom(typeof(T)))
{
var _input = Unsafe.As<T, System.Collections.Generic.IEnumerable<double>>(ref input);
Foo(_input);
return;
}
FooDefault(input);
return;
}
}
Rules
- Both of void-return and non-void-return methods are supported.
- Both of instance and static methods are supported.
- If primary generic method is an instance method, both of instance and static methods are available as specialization or default.
- If primary generic method is a static method, only static methods are available as specialization or default.
- Primary generic method declaration must has accessibility modifier.
- Generic specialization method must has same signature with primary generic method except that the generic type arguments are replaced by concrete types.
- Generic specialization method must be in the same class with primary generic method declaration.
Limitation
These might be changed in future.
- Partial specialization is not supported now.
- where only some of the multiple type arguments are determined
- where type constraints become stricter instead of concrete types being substituted
License
Apache License Version 2.0
Release Note
v0.1.0
- Adds a source generator to add
GenericSpecialization.PrimaryGenericAttribute
class and generate generic specialization code.
v0.1.1
- Fixes some bugs
- Adds framework version check for MethodImplOptions.AggressiveOptimization
- Supports type constraints
v0.1.2
- Fixes to supports overloading
v0.1.3
- Supports parameter modifiers (
ref
/in
/out
)
v0.1.4
- Supports struct/interface
- Supports inner type
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.