C# Cheatsheet

Errors, Nullability, and Resources

Use this C# reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Exceptions and Filters

try {
    int n = int.Parse(text);
} catch (FormatException ex) when (text.Length > 0) {
    Console.WriteLine(ex.Message);  // `when` filter: only catches if the condition holds
} catch (OverflowException) {
    Console.WriteLine("number too large for int");
} finally {
    Console.WriteLine("cleanup, runs either way");
}

Catch the most specific exception you can handle. Exception filters (catch ... when) skip the handler without unwinding, so failing filters leave the original stack intact for the next handler.

Throwing, Guard Helpers, and Rethrowing

static int Divide(int a, int b)
{
    if (b == 0) throw new ArgumentException("b must not be zero", nameof(b));
    return a / b;
}

static void Save(string? name, object? payload, int retries)
{
    ArgumentNullException.ThrowIfNull(payload);       // throws with the parameter name
    ArgumentException.ThrowIfNullOrWhiteSpace(name);  // .NET 8+
    ArgumentOutOfRangeException.ThrowIfNegative(retries);
}

try {
    Work();
} catch (Exception ex) {
    Log(ex);
    throw;      // rethrow: preserves the original stack trace
    // throw ex;  // WRONG: resets the stack trace to this line
}

Custom Exceptions

public class OrderNotFoundException : Exception
{
    public int OrderId { get; }

    public OrderNotFoundException(int orderId)
        : base($"Order {orderId} was not found") => OrderId = orderId;

    public OrderNotFoundException(int orderId, Exception inner)
        : base($"Order {orderId} was not found", inner) => OrderId = orderId;
}

Derive from Exception, end the name with Exception, and carry structured data as properties. Pass the causing exception as innerException when wrapping.

Null Checks

static int LengthOrZero(string? s) => s is null ? 0 : s.Length;

string name = maybeName ?? "Anonymous";     // fallback when null
maybeName ??= "Anonymous";                  // assign only if currently null
string? email = maybeUser?.Profile?.Email;  // null if any step is null
int len = maybeName!.Length;                // ! null-forgiving: silences the warning only

?? supplies a fallback and ?. short-circuits to null. The null-forgiving ! tells the compiler "trust me, this is not null". It changes nothing at runtime, so a wrong ! still throws NullReferenceException.

using and IDisposable

using var reader = File.OpenText("input.txt");  // disposed at end of scope
string all = reader.ReadToEnd();

using (var stream = File.OpenRead("data.bin"))
{
    // disposed at the end of this block
}

await using var log = File.OpenWrite("app.log");  // IAsyncDisposable

using disposes resources such as files, streams, database connections, and HTTP responses even when an exception happens. await using is the async counterpart for types implementing IAsyncDisposable.

File Basics

using System.IO;

File.WriteAllText("out.txt", "hello");
string text = File.ReadAllText("out.txt");
string[] lines = File.ReadAllLines("out.txt");

await File.WriteAllTextAsync("out.txt", "hello");
string contents = await File.ReadAllTextAsync("out.txt");
bool exists = File.Exists("out.txt");

For large files, prefer streaming APIs (File.ReadLines, StreamReader) instead of reading everything into memory at once.