C# Cheatsheet

Complete C# reference. Hit Ctrl+P to print.

Variables & Types

int x = 42;Integer (32-bit signed)
long x = 42L;64-bit signed integer
double x = 3.14;64-bit floating point
float x = 3.14f;32-bit floating point
decimal x = 3.14m;128-bit decimal — use for money/finance
bool x = true;Boolean
char x = 'A';Single UTF-16 character
string s = "hello";Immutable Unicode string
object o = 42;Base type of all types — boxing
var x = 42;Implicitly typed — compiler infers type at compile time
int? x = null;Nullable value type
x ?? "default"Null-coalescing — use default if null
x ??= "default"Null-coalescing assignment
x?.PropertyNull-conditional — returns null if x is null
const int MAX = 100;Compile-time constant
readonly int max;Runtime constant — can only be set in constructor
(int a, string b) = (1, "hi");Tuple deconstruction
var (x, y) = GetPoint();Deconstruct method return

Strings

$"Hello, {name}!"String interpolation (preferred)
$"Pi is {Math.PI:F2}"Interpolation with format specifier
@"C:\Users\file"Verbatim string — backslashes are literal
"""multiline"""Raw string literal (C# 11+)
"a" + "b"Concatenation — use StringBuilder for many ops
string.Concat(a, b)Concatenate without + operator
string.Join(", ", arr)Join array into string with separator
s.LengthNumber of characters
s.ToUpper() / s.ToLower()Change case
s.Trim() / s.TrimStart() / s.TrimEnd()Strip whitespace
s.Contains("sub")True if substring found
s.StartsWith("pre") / s.EndsWith("suf")Check prefix / suffix
s.IndexOf("sub")First index of substring (-1 if not found)
s.Substring(2, 5)Extract: start index, length
s[2..5]Range slice (C# 8+) — same as Substring(2, 3)
s.Replace("a", "b")Replace all occurrences
s.Split(",")Split into string array on delimiter
s.PadLeft(10, '0')Left-pad to width with character
string.IsNullOrEmpty(s)True if null or ""
string.IsNullOrWhiteSpace(s)True if null, empty, or only whitespace
int.Parse(s) / int.TryParse(s, out var n)Parse string to int — TryParse avoids exception

Collections

int[] arr = {1, 2, 3};Fixed-size array
int[] arr = new int[5];Array of size 5, default-initialised to 0
arr.LengthNumber of elements
arr[^1]Last element using index-from-end (C# 8+)
arr[1..3]Array slice: elements at index 1 and 2
var list = new List<int> { 1, 2, 3 };Generic list — resizable
list.Add(4) / list.AddRange(other)Append element / append collection
list.Insert(0, 99)Insert at index
list.Remove(2) / list.RemoveAt(0)Remove by value / by index
list.Contains(3)True if value exists
list.CountNumber of elements
list.Sort() / list.Reverse()Sort / reverse in place
var dict = new Dictionary<string, int>();Key-value store
dict["key"] = 1 / dict.Add("key", 1)Set value / add (throws if key exists)
dict.TryGetValue("key", out var val)Safe access — returns false if missing
dict.ContainsKey("key")True if key exists
dict.Keys / dict.ValuesCollections of keys / values
var set = new HashSet<int> { 1, 2, 3 };Unordered unique elements
set.Add(4) / set.Contains(2)Add / check membership
set.UnionWith(other) / set.IntersectWith(other)Set operations
var q = new Queue<int>(); q.Enqueue(1); q.Dequeue();FIFO queue
var s = new Stack<int>(); s.Push(1); s.Pop();LIFO stack

Control Flow

if (x > 0) { } else if (x < 0) { } else { }Conditional branches
x > 0 ? "pos" : "neg"Ternary operator
switch (x) { case 1: break; default: break; }Classic switch — falls through without break
x switch { 1 => "one", 2 => "two", _ => "other" }Switch expression (C# 8+) — returns a value
x switch { > 0 => "pos", < 0 => "neg", _ => "zero" }Switch expression with relational patterns
if (obj is string s) { }Pattern matching with type check and binding
if (obj is { Length: > 0 })Property pattern match
for (int i = 0; i < 10; i++) { }C-style for loop
foreach (var item in collection) { }Iterate any IEnumerable
while (x > 0) { }Loop while true
do { } while (x > 0);Execute at least once
break / continueExit loop / skip to next iteration
goto label; ... label:Jump to label (use sparingly)

Methods

public int Add(int a, int b) => a + b;Expression-bodied method
public void Log(string msg, bool verbose = false)Optional parameter with default
public int Sum(params int[] nums)params — pass any number of args
fn(b: 2, a: 1)Named arguments — order independent
public void Swap(ref int a, ref int b)ref — pass by reference (must be initialised)
public bool TryParse(string s, out int result)out — write-only out param (need not be initialised)
Func<int, int> square = x => x * x;Lambda stored as Func delegate
Action<string> log = s => Console.WriteLine(s);Lambda stored as Action (void return)
public static T Identity<T>(T value) => value;Generic method
public int this[int i] => items[i];Indexer

Classes & OOP

class Dog : Animal, IRunnable { }Class inheriting Animal and implementing interface
public Dog(string name) : base(name) { }Constructor calling base constructor
public string Name { get; set; }Auto property
public string Name { get; init; }Init-only property — settable only in object initialiser
public string Name { get; private set; }Publicly readable, privately writable
var d = new Dog { Name = "Rex" };Object initialiser syntax
public override string ToString() => Name;Override virtual method
public virtual void Speak() { }Virtual — can be overridden by subclass
public abstract void Speak();Abstract method — must be implemented by subclass
sealed class Singleton { }Sealed — cannot be subclassed
static class MathUtils { }Static class — cannot be instantiated, all members static
record Point(double X, double Y);Record — immutable, value-equality, auto ToString (C# 9+)
record struct Point(double X, double Y);Record struct — stack-allocated record (C# 10+)
interface IDrawable { void Draw(); }Interface — contract with no implementation
interface ILogger { void Log(string msg) => Console.WriteLine(msg); }Default interface method (C# 8+)
enum Direction { North, South, East, West }Enum — named integer constants
[Flags] enum Perms { Read = 1, Write = 2, Execute = 4 }Flags enum for bitmask combinations
obj is Dog dogPattern match and bind to typed variable
obj as DogSafe cast — returns null if not compatible
(Dog) objDirect cast — throws InvalidCastException if incompatible

LINQ

using System.Linq;Required namespace
list.Where(x => x > 0)Filter — returns IEnumerable
list.Select(x => x * 2)Transform each element
list.SelectMany(x => x.Items)Flatten nested collections
list.First() / list.FirstOrDefault()First element — FirstOrDefault returns null/default if empty
list.Single() / list.SingleOrDefault()Exactly one element — throws if more than one
list.Last() / list.LastOrDefault()Last element
list.Any(x => x > 0)True if any element matches predicate
list.All(x => x > 0)True if all elements match predicate
list.Count() / list.Count(x => x > 0)Count all / count matching
list.Sum(x => x.Price)Sum of projected values
list.Min(x => x.Age) / list.Max(x => x.Age)Min / max of projected values
list.Average(x => x.Score)Average of projected values
list.OrderBy(x => x.Name)Sort ascending
list.OrderByDescending(x => x.Age).ThenBy(x => x.Name)Sort descending, then secondary sort
list.GroupBy(x => x.Category)Group into IGrouping
list.Distinct()Remove duplicates
list.Skip(5).Take(10)Pagination — skip N, take M
list.ToList() / list.ToArray() / list.ToDictionary(x => x.Id)Materialise to collection
from x in list where x > 0 select x * 2Query syntax — equivalent to method syntax

Async / Await

public async Task<int> GetCountAsync()Async method returning a value
public async Task DoWorkAsync()Async method with no return value
var result = await SomeAsync();Await a Task — suspends until complete
await Task.Delay(1000);Non-blocking delay of 1 second
var t1 = Foo(); var t2 = Bar(); await Task.WhenAll(t1, t2);Run concurrently, wait for both
await Task.WhenAny(t1, t2)Complete when the first task finishes
Task.Run(() => HeavyWork())Run synchronous work on thread pool
await foreach (var item in GetItemsAsync())Async enumeration (IAsyncEnumerable)
CancellationTokenSource cts = new(); cts.Cancel();Cancel a running operation
async Task Fn(CancellationToken ct) { ct.ThrowIfCancellationRequested(); }Respect cancellation token
.ConfigureAwait(false)Do not marshal back to original context — use in libraries
ValueTask<int>Allocation-free alternative to Task for hot paths

Exception Handling

try { } catch (Exception ex) { } finally { }Try/catch/finally — finally always runs
catch (IOException ex) when (ex.HResult == -1)Exception filter with when clause
catch (IOException) catch (ArgumentException)Multiple catch blocks — most specific first
throw new ArgumentException("bad arg");Throw an exception
throw;Re-throw preserving original stack trace
throw new ArgumentNullException(nameof(param));nameof avoids magic strings
ex.Message / ex.StackTrace / ex.InnerExceptionCommon exception properties
class AppException : Exception { }Custom exception class
ArgumentNullException.ThrowIfNull(value);Guard helper (C# 10+)