オーバーロード関数の優先順位を指定するOverloadResolutionPriority属性(Overload resolution priority)
C# 13では、オーバーロード関数の優先順位を指定するOverloadResolutionPriority属性が利用できるようになりました。
C#の言語仕様の拡張に伴い、従来からあるメソッドに優先して新しいメソッドを使う方が望ましいとされています。ただし、互換性の観点から従来のメソッドを削除できず、思うように新しいメソッドを使えないという問題があります。例えば、メソッドの引数がIEnumerable<T>型であるメソッドに加えて、比較的新しい型であるReadOnlySpan<T>を引数とするメソッドを追加したケースです。
C# 13においても、以下のリストはコンパイルエラー「次のメソッドまたはプロパティ間で呼び出しが不適切です」となります。
var c = new C();
var a = new int[10];
c.Method(a);
class C
{
public void Method(IEnumerable<int> _e) { Console.WriteLine("IEnumerable"); }
public void Method(Span<int> _s) { Console.WriteLine("Span");}
public void Method(ReadOnlySpan<int> _r) { Console.WriteLine("ReadOnlySpan"); }
}
それぞれのメソッドにOverloadResolutionPriority属性を付与することで、オーバライドされたメソッド間で優先順位を指定できます。OverloadResolutionPriority(0)は、属性を指定しない場合と同等となり、正数で優先度を上げて、負数で優先度を下げます。
using System.Runtime.CompilerServices;
…略…
c.Method(a); // ReadOnlySpan
…略…
[OverloadResolutionPriority(-1)]
public void Method(IEnumerable<int> _e) { Console.WriteLine("IEnumerable"); }
public void Method(Span<int> _s) { Console.WriteLine("Span");}
[OverloadResolutionPriority(1)]
public void Method(ReadOnlySpan<int> _r) { Console.WriteLine("ReadOnlySpan"); }
このように、主にライブラリ作成者が新しいオーバロードの追加時に曖昧さを回避できることを想定した機能と言えます。逆に、意図しないオーバロードが呼び出される可能性もあるので、この属性は慎重に利用する必要があります。
まとめ
今回は、暗黙的なインデックスアクセス、イテレータと非同期メソッドで使えるようになったrefとunsafe、ジェネリクスの型制約に使えるようになったallows ref struct、partialなプロパティとインデクサ、オーバーロード関数の優先順位を指定するOverloadResolutionPriority属性を紹介しました。
C#の新バージョンでは、本連載で紹介したように、より使い勝手を良くする改変が施されています。よりモダンで使い勝手のよい言語として成長し続けるC#を、今後も見守っていきたいものです。
