Static Abstract Members in Interfaces

C# 11.0 .NET 7.0

Published Updated Author Jeffrey T. Fritz Reading time

Define compile-time contracts for static members so generic algorithms can call them safely.

C# 11 allows interfaces to require static members. This unlocks new generic patterns where code can call operators and factory methods on a constrained type parameter.

Why it matters

  • Makes reusable generic math and parsing APIs practical.
  • Moves many runtime checks to compile time.
  • Enables cleaner abstractions for numeric and strongly-typed value objects.

Cautions

This feature is powerful but advanced. Keep examples focused, because excessive generic constraints can quickly become hard to read for teams unfamiliar with generic math patterns.

Constrain generic parsing with static abstract members

Call static members through generic constraints for compile-time-safe abstractions.

Valid since C# 11.0

using System;

public interface ISpanParsableValue<TSelf> where TSelf : ISpanParsableValue<TSelf>
{
    static abstract TSelf Parse(ReadOnlySpan<char> value);
}

public readonly record struct ProductCode(string Value) : ISpanParsableValue<ProductCode>
{
    public static ProductCode Parse(ReadOnlySpan<char> value) => new(value.ToString().Trim().ToUpperInvariant());
}

public static class Program
{
    private static T ParseValue<T>(ReadOnlySpan<char> input) where T : ISpanParsableValue<T>
    {
        return T.Parse(input);
    }

    public static void Main()
    {
        var code = ParseValue<ProductCode>(" abc-42 ");
        Console.WriteLine(code.Value); // ABC-42
    }
}

Model reusable numeric operations

Static abstract operators enable type-safe generic math patterns.

Valid since C# 11.0

using System;

public interface IAddable<TSelf> where TSelf : IAddable<TSelf>
{
    static abstract TSelf operator +(TSelf left, TSelf right);
}

public readonly record struct Distance(int Meters) : IAddable<Distance>
{
    public static Distance operator +(Distance left, Distance right) => new(left.Meters + right.Meters);
}

public static class Program
{
    private static T Sum<T>(T left, T right) where T : IAddable<T>
    {
        return left + right;
    }

    public static void Main()
    {
        var combined = Sum(new Distance(150), new Distance(275));
        Console.WriteLine(combined.Meters); // 425
    }
}

Learn more

Static abstract and virtual members (Microsoft Learn)