rksoftware

Visual Studio とか C# とかが好きです

C# 13 の新機能「OverloadResolutionPriority 属性」その 1

.NET 9 Preview 7 で C# 13 の新機能「OverloadResolutionPriority」属性が追加されました。
オーバーロードの解決の優先順位を操作できる属性のようです。
今回はそのお試しその 1 です。

その 2、3 はこちら

rksoftware.hatenablog.com rksoftware.hatenablog.com

■ 前提 メソッドのオーバーロード

メソッドのオーバーロードとは同じ名前で違う引数のメソッドです。場合によっては同じ名前のどのメソッドでも適合してしまうコードというのがあります。次のように

// 引数 2 つのメソッドの二つ目の引数がデフォルト値をもつので、
// このコードは引数 1 つのメソッドでも引数 2 つのメソッドでもどちらでも成立する
Class1.Test(1);

static class Class1
{
    public static void Test(int a) => Console.WriteLine("Class1:   ,  : 引数 1 つ");
    public static void Test(int a, int b = 0) => Console.WriteLine("Class1:   ,  : 引数 2 つ");
}

その場合にどのメソッドが優先されるかのルールがあるのですが、そのルールより優先した優先度を自分でつけられます。

■ 実例

このようになります。大きい数値を指定したものがより優先となるようです。同じ数値を指定するとその中で標準のルール。基準値は 0 のようです。

Class1.Test(1); // Class1:   ,  : 引数 1 つ / 何もしていないと普通の順番
Class2.Test(1); // Class2: -1,  : 引数 2 つ / 0 より低い値を設定すると優先度が下がる、引数 1 つメソッドの優先度を下げたので、引数 2 つが選択された
Class3.Test(1); // Class3:   , 0: 引数 1 つ / 0 を指定したものと何も指定していない引数 1 つのメソッドと同じ優先度。標準のルールで引数 1 つのメソッド選択された
Class4.Test(1); // Class4:   , 1: 引数 2 つ / 0 よりも大きい値を指定すると優先度が上がる。引数 2 つのメソッドの優先度を上げたので、引数 2 つが選択された
Class5.Test(1); // Class5:  1, 1: 引数 1 つ / 同じ値を指定すると同じ優先度。標準のルールで引数 1 つのメソッド選択された

static class Class1
{
    public static void Test(int a) => Console.WriteLine("Class1:   ,  : 引数 1 つ");
    public static void Test(int a, int b = 0) => Console.WriteLine("Class1:   ,  : 引数 2 つ");
}

static class Class2
{
    [System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
    public static void Test(int a) => Console.WriteLine("Class2: -1,  : 引数 1 つ");
    public static void Test(int a, int b = 0) => Console.WriteLine("Class2: -1,  : 引数 2 つ");
}

static class Class3
{
    public static void Test(int a) => Console.WriteLine("Class3:   , 0: 引数 1 つ");
    [System.Runtime.CompilerServices.OverloadResolutionPriority(0)]
    public static void Test(int a, int b = 0) => Console.WriteLine("Class3:   , 0: 引数 2 つ");
}

static class Class4
{
    public static void Test(int a) => Console.WriteLine("Class4:   , 1: 引数 1 つ");
    [System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
    public static void Test(int a, int b = 0) => Console.WriteLine("Class4:   , 1: 引数 2 つ");
}

static class Class5
{
    [System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
    public static void Test(int a) => Console.WriteLine("Class5:  1, 1: 引数 1 つ");
    [System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
    public static void Test(int a, int b = 0) => Console.WriteLine("Class5:  1, 1: 引数 2 つ");
}

■ 下位互換で活躍

ライブラリなどをアップデートするときに下位互換を維持しながら新機能 (新メソッド) を追加するときなどに活躍すると思います。
しっかり使いこなして行きましょう。