Skip to content

Instantly share code, notes, and snippets.

@timheuer
Created April 10, 2025 23:58
Show Gist options
  • Save timheuer/c3e9d811df1dc2c03119a4b5c6ede6a2 to your computer and use it in GitHub Desktop.
Save timheuer/c3e9d811df1dc2c03119a4b5c6ede6a2 to your computer and use it in GitHub Desktop.
copilot-instructions for C#

GitHub Copilot Instructions

Prefer C# 12 and 13 Language Features

Primary Constructors

Use primary constructors to simplify your class and struct definitions.

public class Person(string name, int age) {
    public void Deconstruct(out string name, out int age) => (name, age) = (this.name, this.age);
}

Collection Expressions

Use collection expressions for concise and readable collection initialization.

int[] numbers = [1, 2, 3, 4, 5];
List<string> words = ["one", "two", "three"];

Default Lambda Parameters

Define default values for parameters on lambda expressions.

Func<int, int, int> add = (x, y = 5) => x + y;
Console.WriteLine(add(3)); // Output: 8

ref readonly Parameters

Use ref readonly parameters to improve API clarity.

void ProcessData(ref readonly int data) {
    // Use data without modifying it
}

Alias Any Type

Use the using alias directive to create semantic aliases for complex types.

using IntPair = (int first, int second);
IntPair pair = (1, 2);

Inline Arrays

Use inline arrays for performance-sensitive scenarios in structs.

[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer {
    private int _element0;
}

params Collections

Utilize params collections to simplify method parameter definitions.

public void Concat<T>(params ReadOnlySpan<T> items) {
    for (int i = 0; i < items.Length; i++) {
        Console.Write(items[i]);
        Console.Write(" ");
    }
    Console.WriteLine();
}

New Lock Object

Use the System.Threading.Lock type for improved thread synchronization.

var myLock = new Lock();
using (myLock.EnterScope()) {
    // Critical section
}

New Escape Sequence

Use \e as a character literal escape sequence for the ESCAPE character.

char escapeChar = '\e';

Method Group Natural Type

Optimize method overload resolution using method group natural type improvements.

var printAction = (string s) => Console.WriteLine(s);
printAction("Hello, C# 13!");

Implicit Index Access

Use the ^ operator in object initializers for implicit "from the end" indexing.

public class TimerRemaining {
    public int[] buffer { get; set; } = new int[10];
}
var countdown = new TimerRemaining() {
    buffer = { [^1] = 0, [^2] = 1, [^3] = 2, [^4] = 3, [^5] = 4 }
};

ref and Unsafe in Iterators and Async Methods

Allow ref local variables and unsafe contexts in iterator and async methods.

async Task ProcessDataAsync() {
    ref int localRef = ref someRefVariable;
    await Task.Delay(1000);
    // Usage of localRef within the same scope
}

Partial Properties and Indexers

Declare partial properties and indexers for more modular code.

public partial class MyClass {
    public partial string Name { get; set; }
}
public partial class MyClass {
    private string _name;
    public partial string Name {
        get => _name;
        set => _name = value;
    }
}

Overload Resolution Priority

Use the OverloadResolutionPriorityAttribute to prioritize method overloads.

public class MyClass {
    [OverloadResolutionPriority(1)]
    public void Method(int a) { }

    [OverloadResolutionPriority(2)]
    public void Method(int a, int b) { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment