Skip to content

Commit

Permalink
Update attributes language reference
Browse files Browse the repository at this point in the history
  • Loading branch information
BillWagner committed Sep 4, 2024
1 parent 28be8eb commit f8a35e5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
15 changes: 15 additions & 0 deletions docs/csharp/language-reference/attributes/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ There are several attributes that can be applied to elements in your code that a
- [`ModuleInitializer`](#moduleinitializer-attribute): Declare a method that initializes a module.
- [`SkipLocalsInit`](#skiplocalsinit-attribute): Elide the code that initializes local variable storage to 0.
- [`UnscopedRef`](#unscopedref-attribute): Declare that a `ref` variable normally interpreted as `scoped` should be treated as unscoped.
- [`OverloadResolutionPriority`](#overloadresolutionpriority-attribute): Add a tiebreaker attribute to influence overload resolution for possibly ambiguous overloads.
- [`Experimental`](#experimental-attribute): Mark a type or member as experimental.

The compiler uses those semantic meanings to alter its output and report possible mistakes by developers using your code.
Expand Down Expand Up @@ -229,6 +230,20 @@ You add this attribute where the compiler treats a `ref` as implicitly `scoped`:

Applying the <xref:System.Diagnostics.CodeAnalysis.UnscopedRefAttribute?displayProperty=nameWithType> marks the element as unscoped.

## `OverloadResolutionPriority` attribute

The <xref:System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute> enables library authors to prefer one overload over another when two overloads can be ambiguous. Its primary use case is for library authors to write better performing overloads while still supporting existing code without breaks.

For example, you might add a new overload that uses <xref:System.ReadOnlySpan%601> to reduce memory allocations:

:::code language="csharp" source="snippets/OrpaExample.cs" ID="SnippetOverloadExample":::

Overload resolution considers the two methods equally good for some argument types. For an argument of `int[]`, it prefers the first overload. To get the compiler to prefer the `ReadOnlySpan` version, you can increase the priority of that overload. The following example show the effect of adding the attribute:

:::code language="csharp" source="snippets/OrpaExample.cs" ID="SnippetOrpaExample":::

Library authors should use this attribute as a last resort when adding a new and better method overload. Library authors should have a deep understanding of how [Overload resolution](~/_csharplang/proposals/overload-resolution-priority.md#overload-resolution-priority) impacts choosing the better method. Otherwise, unexpected errors can result.

## See also

- <xref:System.Attribute>
Expand Down
25 changes: 25 additions & 0 deletions docs/csharp/language-reference/attributes/snippets/OrpaSnippets.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Runtime.CompilerServices;

namespace attributes;
public class OverloadExample
{

public static void OrpaExample()
{
// <SnippetOrpaExample>
var d = new OverloadExample();
int[] arr = [1, 2, 3];
d.M(1, 2, 3, 4); // Prints "Span"
d.M(arr); // Prints "Span" when PriorityAttribute is applied
d.M([1, 2, 3, 4]); // Prints "Span"
d.M(1, 2, 3, 4); // Prints "Span"
// </SnippetOrpaExample>
}

// <SnippetOverloadExample>
[OverloadResolutionPriority(1)]
public void M(params ReadOnlySpan<int> s) => Console.WriteLine("Span");
// Default overload resolution priority of 0
public void M(params int[] a) => Console.WriteLine("Array");
// </SnippetOverloadExample>
}
3 changes: 3 additions & 0 deletions docs/csharp/language-reference/attributes/snippets/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using attributes;
using AttributeExamples;


OverloadExample.OrpaExample();

TraceExample.Main();
ObsoleteProgram.Main();
ModuleInitializerExampleMain.Main();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down

0 comments on commit f8a35e5

Please sign in to comment.