C# Cheatsheet
Collections and LINQ
Use this C# reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Arrays, List<T>, and Collection Expressions
int[] fixedScores = [90, 80, 100]; // collection expression (C# 12) fixedScores[0] = 95; List<int> scores = [90, 80]; scores.Add(100); scores.RemoveAt(0); Console.WriteLine(scores.Count); int[] merged = [..fixedScores, ..scores, 42]; // spread int[] empty = [];
Arrays have fixed length. List<T> grows and is the default everyday sequence type. Collection expressions target arrays, lists, spans, and any collection interface.
Dictionary and HashSet
var counts = new Dictionary<string, int>(); counts["apple"] = 1; counts["apple"]++; if (counts.TryGetValue("apple", out int c)) { Console.WriteLine(c); } foreach (var (word, count) in counts) { Console.WriteLine($"{word}: {count}"); } var seen = new HashSet<string>(); bool added = seen.Add("csharp"); // false on duplicates bool member = seen.Contains("csharp");
Use dictionaries for key-to-value lookup and sets for uniqueness/membership. Both are O(1) average per operation.
Queue, Stack, and PriorityQueue
var q = new Queue<string>(); q.Enqueue("first"); string head = q.Peek(); string served = q.Dequeue(); var stack = new Stack<int>(); stack.Push(1); int top = stack.Pop(); var pq = new PriorityQueue<string, int>(); pq.Enqueue("low", 5); pq.Enqueue("urgent", 1); string next = pq.Dequeue(); // "urgent": lowest priority value first
Queues are FIFO; stacks are LIFO. PriorityQueue is a min-heap: negate the priority (or pass a reversed IComparer) for max-heap behavior.
Sorted Collections
var ranks = new SortedDictionary<string, int>(); // keys kept in order, O(log n) ranks["beta"] = 2; ranks["alpha"] = 1; // iterates alpha, beta var window = new SortedSet<int> { 5, 1, 3 }; int min = window.Min; int max = window.Max; var slice = window.GetViewBetween(2, 5); // {3, 5}
Reach for these when you need ordered iteration or min/max under inserts and removals, the classic interview substitute for a balanced BST.
Sorting and Comparers
int[] a = [5, 1, 4]; Array.Sort(a); // ascending in place Array.Sort(a, (x, y) => y.CompareTo(x)); // descending via comparison var people = new List<(string Name, int Age)> { ("Ada", 36), ("Alan", 41) }; people.Sort((p, q) => p.Age.CompareTo(q.Age)); // List<T>.Sort, in place var byName = people.OrderBy(p => p.Name).ToList(); // LINQ, returns a new list
Array.Sort/List<T>.Sort are in-place and unstable; OrderBy allocates a new sequence and is stable.
LINQ Core Methods
using System.Linq; int[] nums = [1, 2, 3, 4, 5]; var evens = nums.Where(n => n % 2 == 0).ToList(); int[] squares = nums.Select(n => n * n).ToArray(); int sum = nums.Sum(); double avg = nums.Average(); int count = nums.Count(n => n > 2); int first = nums.First(n => n > 3); // throws if none match int maybe = nums.FirstOrDefault(n => n > 99); // 0 if none match bool anyEven = nums.Any(n => n % 2 == 0); // true bool allPositive = nums.All(n => n > 0); // true bool hasThree = nums.Contains(3); int[][] nested = [[1, 2], [3], [4, 5]]; int[] flat = nested.SelectMany(inner => inner).ToArray(); // [1, 2, 3, 4, 5] int[] uniq = new[] { 1, 1, 2, 2, 3 }.Distinct().ToArray(); // [1, 2, 3] int productAll = nums.Aggregate(1, (acc, n) => acc * n); // 120 var taken = nums.Skip(1).Take(2).ToList(); // [2, 3] var chunks = nums.Chunk(2).ToList(); // [1,2], [3,4], [5] var zipped = nums.Zip(["a", "b", "c"]).ToList(); // (1,a), (2,b), (3,c)
Where filters, Select transforms; terminal methods such as ToList, Count, Sum, and First execute the query. Everything before them is lazy (deferred execution), so materialize with ToList/ToArray before iterating twice.
MinBy, MaxBy, ToDictionary, ToLookup
var people = new[] { (Name: "Ada", Age: 36), (Name: "Alan", Age: 41) }; var oldest = people.MaxBy(p => p.Age); // (Alan, 41) var youngest = people.MinBy(p => p.Age); // (Ada, 36) Dictionary<string, int> ages = people.ToDictionary(p => p.Name, p => p.Age); var byFirstLetter = people.ToLookup(p => p.Name[0]); // like a grouped dictionary
MaxBy/MinBy return the element, not the key; ToDictionary throws on duplicate keys, ToLookup groups them instead.
LINQ Grouping and Ordering
var words = new[] { "bee", "ant", "bat", "cat" }; var grouped = words.GroupBy(w => w[0]); foreach (var g in grouped) { Console.WriteLine($"{g.Key}: {string.Join(",", g)}"); // b: bee,bat ... } var countsByLength = words .GroupBy(w => w.Length) .ToDictionary(g => g.Key, g => g.Count()); var sorted = words.OrderBy(w => w.Length).ThenBy(w => w).ToList(); var reversed = words.OrderByDescending(w => w).ToList();
LINQ chains should stay readable. If the chain needs comments between every step, a loop may be clearer.