When adding a new, faster overload such as one taking ReadOnlySpan<T> alongside an existing T[] overload, existing callers often keep binding to the old overload or hit ambiguity errors. Library authors had no way to steer callers to the new overload without removing the old one and breaking binary compatibility.
C# 13 introduces OverloadResolutionPriorityAttribute to let library authors specify which overload should be preferred when multiple are applicable. Higher priority values are preferred.
Code
csharp
using System.Runtime.CompilerServices;
var logger = new Logger();
string[] messages = ["hello", "world"];
logger.Log(messages); // Calls the ReadOnlySpan overload
class Logger
{
// New overload, preferred by the compiler
[OverloadResolutionPriority(1)]
public void Log(ReadOnlySpan<string> messages) { }
// Original overload, still available for binary compatibility
public void Log(string[] messages) { }
}csharp
var logger = new Logger();
string[] messages = ["hello", "world"];
logger.Log(messages); // Always calls the string[] overload
class Logger
{
// Adding a span overload did not help callers passing arrays:
// the string[] overload is an exact match, so it always wins
public void Log(ReadOnlySpan<string> messages) { }
public void Log(string[] messages) { }
}Notes
- The default priority is
0; higher values are preferred - Applicable overloads with a lower priority are removed before the usual "better overload" rules run, so priority can override a better conversion such as the exact
string[]match above - Priority only compares overloads declared in the same type
- Primarily designed for library authors evolving APIs without breaking existing callers
- See Static interface members C# 11.0 for the feature that made adding a member to a shipped interface routine, and so made ambiguity likely.