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);
}
Use collection expressions for concise and readable collection initialization.
int[] numbers = [1, 2, 3, 4, 5];
List<string> words = ["one", "two", "three"];
Define default values for parameters on lambda expressions.
Func<int, int, int> add = (x, y = 5) => x + y;
Console.WriteLine(add(3)); // Output: 8
Use ref readonly
parameters to improve API clarity.
void ProcessData(ref readonly int data) {
// Use data without modifying it
}
Use the using
alias directive to create semantic aliases for complex types.
using IntPair = (int first, int second);
IntPair pair = (1, 2);
Use inline arrays for performance-sensitive scenarios in structs.
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer {
private int _element0;
}
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();
}
Use the System.Threading.Lock
type for improved thread synchronization.
var myLock = new Lock();
using (myLock.EnterScope()) {
// Critical section
}
Use \e
as a character literal escape sequence for the ESCAPE character.
char escapeChar = '\e';
Optimize method overload resolution using method group natural type improvements.
var printAction = (string s) => Console.WriteLine(s);
printAction("Hello, C# 13!");
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 }
};
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
}
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;
}
}
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) { }
}