NDepend Blog

Improve your .NET code quality with NDepend

The attribute OverloadResolutionPriority in .NET 9 and C# 13

December 12, 2024 2 minutes read

The attribute OverloadResolutionPriority

With .NET 9, we gain a new tool for managing method overloads: OverloadResolutionPriorityAttribute declared in the namespace System.Runtime.CompilerServices. It lets you set an overload’s priority, guiding the compiler in selecting a default for ambiguous calls.

In C#, method overloading allows multiple methods with the same name but different parameters. This can cause ambiguity as overloads grow. The compiler’s strict rules sometimes lead to unexpected outcomes or require verbose code to clarify the intended overload. This get even worse when ambiguity is caused by default parameters. For example the compiler emit an error in the following situation:

With the new attribute OverloadResolutionPriority this situation can be fixed this way:

OverloadResolutionPriority and implicit conversion

The C# compiler binding processing is a complex beast. Sometime it does some implicit conversion. For example here both calls prints Method B.

The attribute OverloadResolutionPriority can be used to avoid implicit conversion:

OverloadResolutionPriority for library developers

The purpose of introducing the OverloadResolutionPriorityAttribute is to provide library developers with a mechanism to influence the C# compiler’s method binding process. For instance, one might want to prioritizing the use of string.IndexOf(string, StringComparison = Ordinal) over string.IndexOf(string).

Let’s suppose you are publishing a library with this method Method():

You want to refactor Method() to Method(int i = 123) with a default parameter:

Doing so leads to a binary compatibility breaking change. If the client code doesn’t get recompiled a MissingMethodException is thrown at runtime:

Thanks to OverloadResolutionPriorityAttribute the library can be rewritten this way:

If the client code is recompiled it will print Method B. If not recompiled it will print Method A.

OverloadResolutionPriority usage in .NET 9

With NDepend, we analyzed .NET 9 Base Class Library assemblies within the directory C:\Program Files\dotnet\shared\Microsoft.NETCore.App\9.0.0. Only the method Debug.Assert(bool) is tagged so far with OverloadResolutionPriorityAttribute:

OverloadResolutionPriority usage in .NET BCL

This ensures that this overload is preferred over Debug.Assert(bool):

The CallerArgumentExpression attribute let’s capture as a string the expressions passed to a method. Doing so enables more informative error messages in diagnostic or testing APIs.

Future Usage: Apply OverloadResolutionPriority to Span-based overloads

In this API Proposal, Stephen Toub suggests using the OverloadResolutionPriorityAttribute to prioritize ReadOnlySpan<T> extension methods over Span<T> ones, especially when the latter simply delegate to the ReadOnlySpan<T>-based implementation. This approach eliminates the extra call and reduces the pressure on the JIT to inline, while also preventing those additional methods from being retained during AOT trimming.

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *