📏

[Preview版] .NET 7(C# 11) で導入される Generic math

2022/06/15に公開

数値型の演算

これまでの C# では数値型のジェネリック演算ができませんでした。

そのため、intlongで同じことをするために同じ実装を使い回す必要があったりしました。

// ユークリッドの互除法
static class Euclidean
{
    public static int Gcd(int a, int b)
    {
        if (a > b) (a, b) = (b, a);
        while (a > 0)
            (a, b) = (b % a, a);
        return b;
    }
    public static long Gcd(long a, long b)
    {
        if (a > b) (a, b) = (b, a);
        while (a > 0)
            (a, b) = (b % a, a);
        return b;
    }
}

一応、インターフェイスをジェネリック引数にわたすことでジェネリック演算は記述できなくはないです。

しかし、いかんせん可読性は良くないですのであまり多用するものではないです。

関連記事
https://zenn.dev/naminodarie/articles/84aeed5c24cb1f

Generic math

本項の記載はあくまでPreview版を元にしています。リリース時にも同様とは限らないのでご注意ください

.NET 7(C# 11) で Generic math という機能が導入されます。

より一般には static abstract という static メソッドをインターフェイスの制約に持たせることができる機能です。

これによって、演算子(実態はstaticメソッド)をジェネリック演算で使えるようになります。

using System.Numerics;

Console.WriteLine(Euclidean.Gcd(1 << 20, 7 << 22));
Console.WriteLine(Euclidean.Gcd(1L << 20, 7L << 22));
Console.WriteLine(Euclidean.Gcd(1u << 20, 7u << 22));
Console.WriteLine(Euclidean.Gcd(1uL << 20, 7uL << 22));

static class Euclidean
{
    // % 演算子と比較演算子が実装されている型にユークリッドの互除法を適用する。
    public static T Gcd<T>(T a, T b) where T : IModulusOperators<T, T, T>, IComparisonOperators<T, T>
    {
        if (a > b) (a, b) = (b, a);
        while (a > default(T))
            (a, b) = (b % a, a);
        return b;
    }
}
GitHubで編集を提案

Discussion