Emergency server help: get in touch

C# Cheat Sheet: Syntax, LINQ and .NET 10 Essentials

A compact C# reference for C# 12 to 14 on .NET 10, covering syntax, collections, pattern matching, records, LINQ, async and file handling, run on the .NET 10 SDK.

Published 7 min read

Short answer: Modern C# code uses var and nullable reference types, collection expressions such as [1, 2, 3], switch expressions with pattern matching, records for data, and LINQ methods such as Where and Select for queries. Asynchronous work uses async/await with Task. The current release is C# 14 on .NET 10 (LTS), which adds the field keyword, extension properties and dotnet run app.cs for single-file scripts.

The examples in this C# cheat sheet were run with the .NET 10 SDK 10.0.401 (runtime 10.0.12, C# 14) on Linux on 9 October 2026. Each feature notes the C# version that introduced it, so you can tell what works on older projects: C# 12 shipped with .NET 8 and C# 13 with .NET 9.

Running C# with the dotnet CLI

CommandWhat it does
dotnet --list-sdksInstalled SDKs (.NET 10 is the current LTS)
dotnet new console -n appNew console project with top-level statements
dotnet run · dotnet build · dotnet testRun, build or test the project in the current folder
dotnet run app.csRun a single C# file with no project file (.NET 10)
dotnet publish -c Release -r linux-x64 --self-containedBuild a folder you can copy to a server without installing .NET
dotnet add package SerilogAdd a NuGet package to the project

New projects enable <Nullable>enable</Nullable> and implicit using directives, so Program.cs can start straight away with Console.WriteLine("Hi");.

Variables, types and strings

SyntaxWhat it does
int port = 443; · long big = 10_000_000_000L;Integers; underscores aid readability
double load = 0.75; · decimal price = 9.99m;Binary float · exact decimal for money
var host = "web01"; · const int Max = 3;Inferred type · compile-time constant
string? maybe = null;Nullable reference type; the compiler warns on unsafe use
maybe?.Length ?? 0 · maybe ??= "set";Null-conditional, null-coalescing, assign if null
int.Parse("42") · int.TryParse(s, out var n)Parse (throws) · parse and return bool
$"{host}:{port}"Interpolated string
$"{1234567:N0}" · $"{port,6}" · $"{d:yyyy-MM-dd}"Format specifiers: thousands, width, date
@"C:\temp\new"Verbatim string: backslashes are literal
s.Trim() · s.Split(',') · string.Join("-", list)Trim, split, join
s.Contains("ell") · s.StartsWith("he") · s[1..3] · s[^1]Search, range slice, last character
string.IsNullOrWhiteSpace(s)Null, empty or spaces
a.Equals(b, StringComparison.OrdinalIgnoreCase)Case-insensitive compare
new StringBuilder().Append(i)Build strings in a loop
string json = """
    {
      "host": "db01",
      "port": 3306
    }
    """;                                    // raw string literal (C# 11)

string tpl = $$"""{"host": "{{host}}", "port": {{port}}}""";   // {{ }} interpolates, { } is literal

Collections and collection expressions

SyntaxWhat it does
int[] nums = [5, 1, 4]; · List<string> hosts = ["web01", "db01"];Collection expressions (C# 12)
int[] more = [.. nums, 6, 7];Spread one collection into another
hosts.Add(x) · hosts.Insert(0, x) · hosts.Remove(x) · hosts.CountList operations
hosts[^1] · nums[1..3]Index from the end · range
var ports = new Dictionary<string, int> { ["ssh"] = 22 };Dictionary with an initialiser
ports.TryGetValue("https", out var p)Read without risking KeyNotFoundException
ports.GetValueOrDefault("smtp", 25) · ports.TryAdd(k, v)Read with default · add only if missing
foreach (var (k, v) in ports)Deconstruct key-value pairs
counts[w] = counts.GetValueOrDefault(w) + 1;Count occurrences
new HashSet<int>() · new Queue<T>() · new Stack<T>()Set, FIFO queue, LIFO stack
void Log(params ReadOnlySpan<string> items)params with any collection type (C# 13)

Control flow and pattern matching

string status = code < 500 ? "up" : "down";

string cls = code switch                     // switch expression with relational patterns
{
    >= 200 and < 300 => "ok",
    301 or 302 => "redirect",
    >= 400 and < 500 => "client error",
    _ => "server error",
};

static string Describe(object? o) => o switch
{
    null => "null",
    int i when i > 1000 => "big int",
    int i => $"int {i}",
    string { Length: > 0 } s => $"string of {s.Length}",      // property pattern
    Server { Port: 443 } sv => $"https server {sv.Name}",
    int[] and [1, .., var last] => $"array ending {last}",    // list pattern
    _ => "other",
};

if (o is string str && str.Length > 3) Console.WriteLine(str.ToUpper());
if (o is not null) { ... }

Loops are for (int i = 0; i < 3; i++), foreach (var h in hosts), while and do ... while. Use _ to discard a value you do not need, as in var (name, ip, _) = srv;.

Classes, records and properties

record Server(string Name, string Ip, int Port = 22)        // value equality, ToString, with
{
    public string Address => $"{Ip}:{Port}";
}
var copy = srv with { Port = 8443 };

readonly record struct Point(int X, int Y);                   // small immutable value type

class Db(string host, int port = 3306)                        // primary constructor (C# 12)
{
    public string Status { get; private set; } = "down";
    public override string ToString() => $"Db({host}:{port})";
}

class Options
{
    public required string Host { get; init; }                // must be set, then read-only
    public int Port { get; init; } = 3306;
}

class Config
{
    public string Name { get; set => field = value?.Trim()   // field keyword (C# 14)
        ?? throw new ArgumentNullException(nameof(value)); } = "";
}

enum Level { Info = 1, Warn, Error }

C# 14 also adds null-conditional assignment (customer?.Order = order; does nothing when customer is null) and extension blocks, which can declare extension properties as well as methods:

static class Extensions
{
    public static bool IsPrivateIp(this string ip) => ip.StartsWith("10.");   // classic extension method

    extension<T>(IEnumerable<T> source)                                       // C# 14 extension block
    {
        public bool IsEmpty => !source.Any();                                 // hosts.IsEmpty
    }
}

LINQ and lambdas

SyntaxWhat it does
nums.Where(x => x > 2).Select(x => x * 10)Filter and transform (lazy until enumerated)
nums.Sum() · nums.Max() · nums.Average() · nums.Count(x => x % 2 == 0)Aggregates
nums.Any(fn) · nums.All(fn) · nums.FirstOrDefault(fn)Tests and first match (0 or null if none)
OrderBy(h => h.Length).ThenBy(h => h) · OrderByDescending(fn)Sort
Take(2) · Skip(3) · Distinct() · Chunk(2)Paging, de-duplication, batches
hosts.GroupBy(h => h[..2])Groups with Key
hosts.CountBy(h => h[..2])Key and count pairs (.NET 9+)
hosts.Index()Item with its position (.NET 9+)
ToList() · ToArray() · ToDictionary(h => h, h => h.Length)Materialise results
from h in hosts where h.StartsWith("db") select hQuery syntax; compiles to the same methods
Func<int, int> sq = x => x * x; · Action<string> log = m => ...;Delegate types for lambdas

Async, exceptions and using

var results = await Task.WhenAll(Check("web01"), Check("web02"));   // run in parallel

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await Task.Delay(1000, cts.Token);           // throws OperationCanceledException on timeout

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
var res = await http.GetAsync("https://example.com/");
Console.WriteLine((int)res.StatusCode);

try
{
    ParsePort("abc");
}
catch (ConfigException e) when (e.InnerException is FormatException)   // exception filter
{
    Console.WriteLine(e.Message);
}
finally
{
    Console.WriteLine("cleanup");
}

ArgumentException.ThrowIfNullOrEmpty(name);   // guard clauses
ArgumentOutOfRangeException.ThrowIfNegative(port);

A using var declaration disposes the object at the end of the enclosing scope. In a long-running service, reuse one HttpClient (or IHttpClientFactory) instead of creating one per request.

For server admins: files, processes and single-file scripts

SyntaxWhat it does
File.ReadAllText(p) · File.ReadAllLines(p)Whole file · array of lines (small files)
File.ReadLines(p).Count(l => l.Contains("ERROR"))Stream a large file lazily
await foreach (var line in File.ReadLinesAsync(p))Async line-by-line read
File.WriteAllText(p, s) · File.AppendAllText(p, s)Overwrite · append
Directory.CreateDirectory(d) · Directory.EnumerateFiles(d, "*.log", SearchOption.AllDirectories)mkdir -p · recursive search
Path.Combine("/var", "log", "x.log") · Path.GetExtension(p)Build and split paths
new ProcessStartInfo("df") { ArgumentList = { "-h", "/" }, RedirectStandardOutput = true }Run a command without a shell; then Process.Start(psi) and WaitForExitAsync()
JsonSerializer.Deserialize<AppConfig>(json, new JsonSerializerOptions(JsonSerializerDefaults.Web))Parse JSON into a record, case-insensitive
Environment.GetEnvironmentVariable("HOME") · Environment.ProcessorCountEnvironment and host facts
DateTimeOffset.ParseExact(s, "dd/MMM/yyyy:HH:mm:ss zzz", CultureInfo.InvariantCulture)Parse an Apache or Nginx log timestamp

.NET 10 can run one .cs file as a script, with packages declared at the top. Make it executable and it runs like a shell script:

#!/usr/bin/env dotnet
#:package Humanizer@2.14.1
using Humanizer;

var drive = new DriveInfo("/");
Console.WriteLine($"Free on /: {drive.AvailableFreeSpace.Bytes().Humanize()}");
chmod +x diskcheck.cs
./diskcheck.cs                 # or: dotnet run diskcheck.cs

The first run restores packages and compiles, which takes a few seconds; later runs use a cache. Format strings such as P1 and N0 follow the server’s culture, so pass CultureInfo.InvariantCulture when output is parsed by another tool.

Official documentation (checked 9 October 2026): C# language reference · What’s new in C# 14 · What’s new in C# 13 · What’s new in C# 12 · Pattern matching: patterns · What’s new in .NET 10 · File-based apps

C# Cheat Sheet at a glance

C# Cheat Sheet – short answer
In short: A compact C# reference for C# 12 to 14 on .NET 10, covering syntax, collections, pattern matching, records, LINQ, async and file handling, run on the .NET 10 SDK.
C# Cheat Sheet – what this guide covers
C# Cheat Sheet: what this guide covers.

Related guides: Java Cheat Sheet: Syntax, Collections, Records and Streams · PowerShell Cheat Sheet for Windows Server Admins · TypeScript Cheat Sheet: Types, Generics and tsconfig.

Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.

Share this guide

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.