Skip to content

[API Proposal]: OverloadResolutionPriorityAttribute #102173

Closed
@333fred

Description

@333fred

Background and motivation

In order to support the C# proposed feature https://github.com/dotnet/csharplang/blob/d5bab90e846f9b3e9a7a4e552249643148f0194d/proposals/overload-resolution-priority.md, we add a new attribute to the BCL: OverloadResolutionPriorityAttribute. This feature allows applying the attribute to adjust the priority of an overload within a type. This will allow consumers like the rest of the BCL to adjust overload resolution for scenarios where a new, better API should be preferred (but won't be because overload resolution would prefer the existing one), or to resolve scenarios that will otherwise be ambiguous. One prime example is Debug.Assert; with this API, we could adjust void Debug.Assert(bool condition, string? message) to instead be [OverloadResolutionPriority(1)] Debug.Assert(bool condition, [CallerArgumentExpression(nameof(condition))] string? message = ""). The real change here would be a bit more complex due to the number of overloads that Debug.Assert already has, but this is a simple enough example to convey they intent.

API Proposal

namespace System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class OverloadResolutionPriorityAttribute(int priority)
{
    public int Priority => priority;
}

API Usage

using System.Runtime.CompilerServices;

var d = new C1();
int[] arr = [1, 2, 3];
d.M(arr); // Prints "Span"

class C1
{
    [OverloadResolutionPriority(1)]
    public void M(ReadOnlySpan<int> s) => Console.WriteLine("Span");
    // Default overload resolution priority
    public void M(int[] a) => Console.WriteLine("Array");
}

Alternative Designs

No response

Risks

One of the BCL's main uses of OverloadResolutionPriorityAttribute will be to effectively make source-breaking changes while maintaining binary compatibility. Care will have to be taken when using the attribute to ensure only the intended consequences occur. For a few of these cases, it can effectively make specific overloads impossible to call directly, and users would have to resort to using something like delegate conversion, UnsafeAccessor, reflection, or manual IL.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions