Master C# from the ground up
400 lessons, 40 chapters, live runnable on .NET 8. Foundations → control flow → loops + arrays → methods → classes → inheritance → collections → exceptions → generics → delegates + events → regex → async/await → structs/enums/records — with a real capstone in every chapter (Addition Calculator, Quiz App, Rocket Launch, Weather Simulator, BankAccount, Shape Zoo, Inventory Tracker, Resource Pool, Typed Bag, Stock Monitor, Log Parser, Download Aggregator, Vector2D). Every lesson ships prose, runnable code examples, SVG visualizations, pitfall/deeper/tip/FAQ callouts, and stdin/stdout-graded practice.
Hello World → top-level statements → variables → I/O → conversion → operators → strings → errors → Addition Calculator
- Step 1
Hello, World — your first C# program
Every language has its tradition: the first program you write prints "Hello, World" to the screen. In C# this single lin…
Start lesson - Step 2
using directives, namespaces, and comments
The .NET Base Class Library is huge. Thousands of types live inside it — Console, Math, DateTime, File, Random, List, Di…
Start lesson - Step 3
Variables and the string type
A variable is a named slot in memory that holds a value. Once you've named the slot, you can read the value, change it, …
Start lesson - Step 4
Console input — talking to the user
So far our programs have been monologues — we print, the user reads. A program that takes input is a conversation. C# gi…
Start lesson - Step 5
Numeric types — int, double, decimal, char
Strings are great for text, but most programs eventually have to count, measure, or calculate. C# gives you a precise me…
Start lesson - Step 6
Type conversion — cast, Parse, Convert, TryParse
C# is strict about types. You can't assign a double to an int by accident, and you can't add a string to a number. That …
Start lesson - Step 7
Operators, math, and the order of evaluation
Arithmetic in C# uses the same operators you've seen since school: + (plus), - (minus), * (times), / (divide), and % (mo…
Start lesson - Step 8
String formatting — interpolation, escapes, raw strings
We've already met the workhorse — interpolation: $"Hello, {name}!". You can do more than splice variables. Anything insi…
Start lesson - Step 9
Compile-time vs runtime errors
C# code has to pass through two gates before it does anything useful. The first gate is the compiler — it checks that yo…
Start lesson - Step 10
Capstone — the Addition Calculator
Time to combine the chapter. The Addition Calculator is a small program that reads two numbers from the user, validates …
Start lesson
booleans → if/else → logical operators → else-if chains → nested + scope → ternary → switch → switch expressions → string-driven decisions → Quiz App
- Step 11
Booleans and comparison operators
Every interesting program eventually has to make a decision: should I print the success message or the error one? Should…
Start lesson - Step 12
if and else — choosing a path
The if statement is the bedrock of every program. It takes a bool, and if that bool is true, it runs the block of code t…
Start lesson - Step 13
Logical operators — AND, OR, NOT
Most real decisions combine more than one fact. "Is the user logged in AND a paying customer?" "Is the order overdue OR …
Start lesson - Step 14
else if — multi-branch decisions
A binary if/else is enough when the world splits cleanly into two cases. Most of the time it doesn't. Grading: A, B, C, …
Start lesson - Step 15
Nested conditions and variable scope
Sometimes the inner decision depends on the outer one. You only ask "is this user a paying admin?" after you've already …
Start lesson - Step 16
The ternary operator — one-line conditionals
Every if/else assigns a value to something. "If x is positive, set sign to 'plus'; otherwise set sign to 'minus'." Writi…
Start lesson - Step 17
The switch statement — discrete cases
When you're testing one value against a handful of specific constants — a status string, a menu choice, an HTTP code, an…
Start lesson - Step 18
Switch expressions — C# 8's cleaner form
The classic switch statement does one thing: branches code. C# 8 (.NET Core 3, 2019) introduced the switch expression — …
Start lesson - Step 19
String methods that drive decisions
Most conditions in real programs aren't pure number comparisons — they hinge on what the user typed, what came back from…
Start lesson - Step 20
Capstone — the Little Quiz App
The Quiz App is the classic end-of-control-flow project: ask three questions, accept the user's answer for each, track a…
Start lesson
loops overview → for → while → do-while → break/continue → arrays intro → iterating (for/foreach) → multidimensional → jagged → Rocket Launch simulator
- Step 21
Why loops exist — the four flavors in C#
Programs would be tiny if every value got its own line of code. The reality is the opposite: real programs process colle…
Start lesson - Step 22
The for loop — counting with intent
The for loop is the workhorse of imperative code. Its single-line header packs three jobs into one line: the initializer…
Start lesson - Step 23
while loops — condition-driven iteration
A while loop runs its body as long as a condition is true. Its shape is the simplest of any loop: while (condition) { … …
Start lesson - Step 24
do-while — run first, ask later
while checks the condition before each iteration. do-while checks it AFTER. That single difference makes do-while the ri…
Start lesson - Step 25
break and continue — escape hatches
Most loops finish naturally — the counter reaches the boundary, the queue empties, the condition flips. Sometimes you wa…
Start lesson - Step 26
Arrays — fixed-size collections of one type
Up to now every variable has held a single value. Real programs work in collections: a list of names, an array of scores…
Start lesson - Step 27
Walking an array — for, foreach, and Length
Once you have an array, the next thing you do with it is walk all the elements. C# gives you two natural shapes: a for l…
Start lesson - Step 28
Multidimensional arrays — grids in one block
Some data is naturally two-dimensional: a chess board, a spreadsheet, an image, a heat map. C# offers two ways to model …
Start lesson - Step 29
Jagged arrays — arrays of arrays
A multidimensional array (last lesson) is a rectangle — every row the same length. Sometimes the data isn't rectangular:…
Start lesson - Step 30
Capstone — the Rocket Launch simulator
Time to combine the chapter. The Rocket Launch simulator reads launch parameters from stdin, runs a countdown loop, simu…
Start lesson
methods intro → void/return → parameters → multi-params → overloading → defaults + named args → ref/out/in → expression-bodied (=>) → recursion → Weather Simulator
- Step 31
Methods — naming a piece of work
Every program you've written so far has been a single block of top-level statements — read input, do work, print output,…
Start lesson - Step 32
Return types — void vs producing a value
Every method has a return type. The return type is the contract the method makes with its callers: 'when I'm done, I wil…
Start lesson - Step 33
Parameters — passing data into methods
A parameter is a variable that gets its value from the caller when the method is invoked. In the method signature, each …
Start lesson - Step 34
Multiple parameters — order and types matter
Most useful methods take more than one parameter. The signature lists them in order, separated by commas, each with its …
Start lesson - Step 35
Method overloading — same name, different signatures
Sometimes you want one conceptual operation to work with different inputs. Add(int, int) makes sense; so does Add(double…
Start lesson - Step 36
Default values and named arguments
Sometimes a parameter has a sensible default that most callers use, and only some callers override. Rather than writing …
Start lesson - Step 37
ref, out, in — explicit parameter passing
Pass-by-value (the default) means the method gets a copy. Sometimes you actually want the method to MUTATE the caller's …
Start lesson - Step 38
Expression-bodied members — the => shortcut
Many methods are tiny — one return statement, one expression to evaluate. Writing out the full braces, return, semicolon…
Start lesson - Step 39
Recursion — methods that call themselves
A recursive method is one that calls itself. That sounds like an infinite loop waiting to happen — and it is, unless the…
Start lesson - Step 40
Capstone — the Weather Simulator
Time to combine the chapter. The Weather Simulator reads a fixed-size temperature array from stdin and prints a structur…
Start lesson
classes intro → fields → constructors → properties (auto/full/computed) → instance methods → access modifiers → readonly/const/init → static members → constructor chaining → BankAccount
- Step 41
Classes & objects — the noun in OOP
So far every program has been a verb-heavy script: read, compute, print. Methods (Chapter 4) gave us reusable verbs. Rea…
Start lesson - Step 42
Fields — the state each object carries
Every interesting class carries DATA — the values that make one instance different from another. The pieces of data decl…
Start lesson - Step 43
Constructors — building a valid instance
Manually assigning every field after `new` is tedious and error-prone — forget one and you've shipped a half-initialized…
Start lesson - Step 44
Properties — fields with manners
Public mutable fields give callers a free pass: they can write any value at any time. That's fine for trivial examples a…
Start lesson - Step 45
Methods on a class — behaviour bound to state
Methods inside a class (Chapter 4 covered the same syntax for free-floating local functions) become INSTANCE METHODS — t…
Start lesson - Step 46
public, private, protected, internal — who can touch what
Every member of a class — field, property, method, constructor, nested type — has a visibility level. Visibility decides…
Start lesson - Step 47
readonly, const, init — locking down values
Sometimes a value should be settable ONCE — at construction — and never again. Customer.Id, Order.PlacedAt, Point.X — th…
Start lesson - Step 48
static — class-level state and helpers
Every member we've met so far has belonged to an INSTANCE: each Cat has its own Name; each Account has its own Balance. …
Start lesson - Step 49
Multiple constructors — overloading and chaining
Just like methods, constructors can be overloaded — declared multiple times with different parameter lists. The compiler…
Start lesson - Step 50
Capstone — the BankAccount class
Time to combine the chapter. The BankAccount class wires every Chapter 5 idea into one type: a readonly Id (set at const…
Start lesson
inheritance intro (IS-A) → base/derived + protected → virtual/override → base keyword → abstract classes → constructor chains : base(...) → sealed → interfaces → polymorphism → Shape Zoo
- Step 51
Inheritance — building on what you already have
Real domains have overlap. A SavingsAccount, a CheckingAccount, and a CreditAccount all share Balance, Deposit, and With…
Start lesson - Step 52
Base and derived — what gets inherited
Inheritance gives a derived class access to its base's PUBLIC and PROTECTED members. Private members of the base are sti…
Start lesson - Step 53
virtual and override — polymorphic methods
Inheriting a method as-is is the simple case. The interesting case is REPLACING the inherited behaviour — a Dog's Speak …
Start lesson - Step 54
base — extending, not replacing
Sometimes an override doesn't want to REPLACE the base behavior — it wants to EXTEND it. A SavingsAccount.Withdraw shoul…
Start lesson - Step 55
abstract classes — bases you can't instantiate
Sometimes the base class is INCOMPLETE on purpose. An Animal isn't a real animal — it's a template that says 'every anim…
Start lesson - Step 56
Constructor inheritance — : base(args)
When you create a derived-class instance, BOTH the base AND the derived constructor run. The base runs FIRST (so the der…
Start lesson - Step 57
sealed — closing the hierarchy
Inheritance is open by default — anyone can write `class MyDog : Dog { … }` and customize a virtual method. Sometimes th…
Start lesson - Step 58
Interfaces — contracts without implementation
Abstract classes describe both contract AND state. Sometimes you only need the contract — 'whoever you are, you must imp…
Start lesson - Step 59
Polymorphism — one shape, many implementations
POLYMORPHISM is the umbrella term for the behaviour we've been building toward across this chapter. The literal Greek me…
Start lesson - Step 60
Capstone — the Shape Zoo
Time to combine the chapter. The Shape Zoo reads shape definitions from stdin, builds them into a polymorphic array, and…
Start lesson
collections intro → List<T> basics → Contains/Sort/Reverse → lambdas + predicates → LINQ Where/Any/Select → Dictionary<K,V> → ContainsKey/TryGetValue → HashSet<T> → tuples + deconstruction → Inventory Tracker
- Step 61
Collections — beyond fixed-size arrays
Arrays (Chapter 3) are perfect when you know the size up front. Real programs rarely do. A shopping cart grows as the us…
Start lesson - Step 62
List<T> — dynamic, ordered, indexable
List<T> is the most-used collection in C#. It's a wrapper around an array that grows as you add to it. Adding is amortiz…
Start lesson - Step 63
List operations — Contains, IndexOf, Sort, Reverse
List<T> ships with a small set of MEMBER METHODS that cover the common operations beyond add/remove/index. Knowing which…
Start lesson - Step 64
Lambdas and predicates — code as data
Up to now, methods have been NAMED — we declare them with int Add(int a, int b) and call by name. Many List methods need…
Start lesson - Step 65
LINQ basics — Where, Any, Select, Count
LINQ — Language-Integrated Query — is a set of extension methods over `IEnumerable<T>` that let you filter, transform, a…
Start lesson - Step 66
Dictionary<K, V> — key-driven lookup
List<T> is great when you find things by POSITION. When you find things by KEY — a username, an order id, a product code…
Start lesson - Step 67
ContainsKey, TryGetValue, Remove — defensive dictionary code
Reading a missing key from a Dictionary throws KeyNotFoundException — a runtime crash. Defensive code uses the THREE ins…
Start lesson - Step 68
HashSet<T> — unique items, fast Contains
When you only care WHETHER something is in a collection (not its position, not its count, not associated data), HashSet<…
Start lesson - Step 69
Tuples — returning multiple values cleanly
Methods that need to return more than one value have three options. Out parameters (Chapter 4) — works but reads awkward…
Start lesson - Step 70
Capstone — the Inventory Tracker
Time to combine the chapter. The Inventory Tracker reads commands from stdin and operates on a small inventory data stor…
Start lesson
exceptions intro → try/catch basics → multiple catch + filters → finally → throwing + rethrow → built-in types → custom exceptions → best practices → using + IDisposable → Resource Pool
- Step 71
Exceptions — when something goes wrong at runtime
The compiler proves your types align and your syntax parses. It can't prove your file exists, the network is up, or the …
Start lesson - Step 72
try / catch — handling failures gracefully
A `try` block wraps code that might throw. If anything inside throws, execution skips the rest of the try block and jump…
Start lesson - Step 73
Multiple catches — handle different failures differently
A single try can have MANY catch blocks, each handling a different exception type. The first one whose type matches the …
Start lesson - Step 74
finally — code that always runs
Sometimes you need code to run NO MATTER WHAT — whether the try succeeded, whether an exception was caught, or whether a…
Start lesson - Step 75
Throwing exceptions — signalling failure deliberately
Up to now we've been CATCHING exceptions thrown by the framework. Often you need to THROW your own — when a method's pre…
Start lesson - Step 76
The common built-in exception types
.NET's standard library defines hundreds of exception types, but a small set covers 90% of real-world cases. Learning th…
Start lesson - Step 77
Custom exception types — speaking your domain
The built-in exception types cover generic problems. For DOMAIN-SPECIFIC failures, defining your own type makes catches …
Start lesson - Step 78
Exception best practices — when NOT to catch
Throwing is easy; catching well is hard. The single most common exception-handling mistake is OVER-CATCHING — wrapping c…
Start lesson - Step 79
using + IDisposable — guaranteed cleanup
Files, network connections, database handles, locks — these are RESOURCES the OS hands out and expects back. If your cod…
Start lesson - Step 80
Capstone — the Resource Pool
Time to combine the chapter. The Resource Pool capstone simulates a small lease/return system: clients ACQUIRE a resourc…
Start lesson
generics intro → generic class Box<T> → generic methods + inference → multi type parameters → where constraints → generic interfaces → IEnumerable/ICollection/IList hierarchy → Action/Func/Predicate → default(T) + variance → Typed Bag
- Step 81
Generics — write once, type-check everywhere
You've been USING generics since Chapter 7 — `List<T>`, `Dictionary<K, V>`, `HashSet<T>`. Now we go behind the angle bra…
Start lesson - Step 82
Generic classes — Box<T>
A generic class declares one or more type parameters in angle brackets after the class name: `class Box<T> { … }`. Insid…
Start lesson - Step 83
Generic methods — type parameters on the method
Generic CLASSES tie the type parameter to instances — every method on a Box<int> uses int. Generic METHODS tie the param…
Start lesson - Step 84
Multiple type parameters — KeyValue<K, V>
Up to now every example has had ONE type parameter. Real types often need MORE — `Dictionary<K, V>` for key-value lookup…
Start lesson - Step 85
Generic constraints — narrowing what T can be
Inside a generic class or method, the compiler knows nothing about T beyond 'it's some type'. You can only call members …
Start lesson - Step 86
Generic interfaces — contracts parameterised by type
Interfaces follow the same generic rules as classes. `interface IRepository<T> { T Get(int id); void Save(T item); }`. T…
Start lesson - Step 87
The generic collection interfaces — IEnumerable, ICollection, IList
.NET's collection hierarchy is built from a small set of generic interfaces. Knowing them lets you write methods that ac…
Start lesson - Step 88
Action, Func, Predicate — the standard delegate types
A DELEGATE is a typed reference to a method — 'a variable that holds a function'. Before generics, you defined delegate …
Start lesson - Step 89
default(T), nullability, and a peek at variance
Two more pieces of the generics toolkit. The DEFAULT keyword gives you the type's natural 'zero value': 0 for int, false…
Start lesson - Step 90
Capstone — the Typed Bag
Time to combine the chapter. The Typed Bag capstone implements a generic `Bag<T> where T : IComparable<T>` that holds a …
Start lesson
delegates intro → instances + lambda assignment → multicast +=/-= + invocation list → delegates as parameters → events keyword + publisher/subscriber → EventHandler<T> + custom EventArgs → safe firing (?.Invoke + thread copy) → event vs delegate field → observer pattern → Stock Monitor
- Step 91
Delegates — methods as values
Chapter 9 introduced Action, Func, and Predicate — three families of typed function references. Those are all DELEGATES …
Start lesson - Step 92
Storing and invoking delegate instances
Once you have a delegate type, you create INSTANCES by assigning methods to delegate variables. The three syntactic form…
Start lesson - Step 93
Multicast delegates — += and the invocation list
A delegate variable can point at MORE than one method at the same time. When invoked, ALL the assigned methods run in th…
Start lesson - Step 94
Delegates as parameters — building higher-order helpers
Methods that take other methods as parameters are HIGHER-ORDER methods. They let you parameterise BEHAVIOR, not just dat…
Start lesson - Step 95
Events — the publisher-subscriber pattern
Multicast delegates let you broadcast — one invocation runs every registered method. But there's a problem: any code hol…
Start lesson - Step 96
EventHandler<T> and EventArgs — the standard event shape
Most events need to communicate WHAT happened — not just 'something happened.' A click event carries the click position;…
Start lesson - Step 97
Raising events safely — null-check, copy, dispatch
Raising an event sounds simple — `MyEvent.Invoke(this, args)`. But there are three subtle landmines: the event might be …
Start lesson - Step 98
Events vs delegates — when to use which
Events and delegate-typed fields look nearly identical. Both broadcast to multiple subscribers via +=/-=. Both fire by i…
Start lesson - Step 99
The Observer pattern in C# — events as the language primitive
OBSERVER is one of the original Gang of Four design patterns — a way to wire up 'subject' and 'observer' objects so the …
Start lesson - Step 100
Capstone — the Stock Price Monitor
Time to combine the chapter. The Stock Price Monitor capstone implements a publisher (`Stock`) and TWO independent subsc…
Start lesson
regex intro → literals + anchors (^, $, \b) → character classes (\d \w \s + brackets) → quantifiers (* + ? {n,m} + lazy) → groups + alternation → named groups + backreferences → Regex class (IsMatch/Match/Matches + options) → Replace/Split + MatchEvaluator → lookarounds (?=, ?!, ?<=, ?<!) → Log Parser
- Step 101
Regular expressions — patterns for text
A regular expression — REGEX for short — is a small language for describing PATTERNS in text. 'A US phone number is thre…
Start lesson - Step 102
Literals, anchors, and special characters
Most characters in a regex match THEMSELVES — `a` matches the letter a, `5` matches the digit 5, `-` matches a hyphen. T…
Start lesson - Step 103
Character classes — digit, word, whitespace, and brackets
A CHARACTER CLASS is a set of characters; the regex matches ANY ONE character from the set. `[abc]` matches 'a' or 'b' o…
Start lesson - Step 104
Quantifiers — *, +, ?, {n,m}
A QUANTIFIER attaches to the previous element (a literal, a character class, or a group) and says how many times it shou…
Start lesson - Step 105
Groups and alternation — (…) and |
Parentheses serve two jobs in regex. GROUPING: they let you quantify a sequence (`(abc)+`) or apply alternation to a sub…
Start lesson - Step 106
Named groups and backreferences
Numbered groups work but they're FRAGILE — add a paren in the middle of the pattern and every downstream index shifts. N…
Start lesson - Step 107
The Regex class — IsMatch, Match, Matches, options
.NET's regex API lives in `System.Text.RegularExpressions`. The headline type is `Regex` — both a constructible class (f…
Start lesson - Step 108
Replace and Split — text transformations
`Regex.Replace(input, pattern, replacement)` returns a NEW string with every match replaced. `Regex.Replace("hello 42 wo…
Start lesson - Step 109
Lookarounds — assertions that don't consume
Sometimes you want to match a pattern that's followed by (or preceded by) something specific, WITHOUT including that con…
Start lesson - Step 110
Capstone — the Log Parser
Time to combine the chapter. The Log Parser capstone reads structured log lines from stdin and extracts named fields usi…
Start lesson
async intro → Task + Task<T> → async/await keywords → continuations + state machine → Task.WhenAll / WhenAny → async exceptions → CancellationToken → Task.FromResult + CompletedTask → async pitfalls (async void, deadlocks) → Download Aggregator
- Step 111
Async — why your code stops waiting around
Every program you've written so far has been SYNCHRONOUS: each line waits for the previous one to finish before it start…
Start lesson - Step 112
Task and Task<T> — the unit of async work
A `Task` represents an asynchronous operation — something that will eventually complete (or fail, or be canceled). `Task…
Start lesson - Step 113
async and await — the syntax that makes it readable
Tasks were available since .NET 4 (2010). What made async POPULAR was the ASYNC/AWAIT keywords added in C# 5 (2012). The…
Start lesson - Step 114
Continuations — what the compiler is actually doing
When you write `await something`, the compiler doesn't actually pause execution mid-method. It splits the method at the …
Start lesson - Step 115
WhenAll and WhenAny — running tasks in parallel
Awaiting tasks one-by-one runs them in SEQUENCE — wait for the first, then start the second. For 10 independent slow ope…
Start lesson - Step 116
Exceptions in async — try/catch and AggregateException
Async exceptions look almost identical to sync exceptions — that's the point of async/await. When an awaited Task fails,…
Start lesson - Step 117
Cancellation — letting callers stop long-running tasks
Async operations can run for a while. Sometimes the caller decides they shouldn't anymore — the user clicked Cancel, the…
Start lesson - Step 118
Task.CompletedTask, Task.FromResult — already-done tasks
Sometimes an async method has no asynchronous work to do. It implements an `IXxxAsync` interface for consistency but, in…
Start lesson - Step 119
async pitfalls — async void, deadlocks, sync-over-async
Async code has its own set of HAZARDS that don't exist in sync code. Most async bugs trace back to a small set of recurr…
Start lesson - Step 120
Capstone — the Download Aggregator
Time to combine the chapter. The Download Aggregator capstone simulates a concurrent fan-out: it 'downloads' multiple re…
Start lesson
value vs reference types → defining a struct → struct vs class (mutable-struct trap) → enums → [Flags] enums → readonly/immutable structs → records (value equality) → with-expressions + deconstruction → record/class/struct decision matrix → Vector2D capstone
- Step 121
Value types vs reference types — the great divide
Every type in C# falls on one side of a line that shapes how your program behaves: it is either a value type or a refere…
Start lesson - Step 122
Defining a struct
A struct is how you define your own value type. Syntactically it looks almost identical to a class: it can have fields, …
Start lesson - Step 123
struct vs class — choosing, and the mutable-struct trap
Now that you can define both, the practical question is: which should a given type be? The default answer in modern C# i…
Start lesson - Step 124
Enums — names for a fixed set of values
An enum (enumeration) is a value type that gives friendly names to a fixed set of related constants. Instead of scatteri…
Start lesson - Step 125
[Flags] enums — combining options with bits
Sometimes a value isn't one choice from a set but a COMBINATION of independent options: a file can be readable AND writa…
Start lesson - Step 126
readonly structs & immutability by design
We've leaned on the word 'immutable' repeatedly; now let's make it precise and give it teeth with the language features …
Start lesson - Step 127
Records — value equality with one keyword
C# 9 introduced the `record`, a reference type purpose-built for immutable data with value-based equality. A record is s…
Start lesson - Step 128
with-expressions & deconstruction
Records are immutable, so you can't change a property after construction. But you very often want a copy that's the same…
Start lesson - Step 129
record, class, struct & record struct — the decision matrix
You now have four ways to declare a type, and choosing between them is one of the most common design decisions in C#. Le…
Start lesson - Step 130
Capstone — the 2D Vector value type
Time to combine the chapter into one elegant value type. The Geometry capstone builds a `Vector2D` as a `readonly record…
Start lesson
DateTime (ticks + Kind) → Now/Today/UtcNow + constructors → components (DayOfWeek/DayOfYear) → TimeSpan (component vs Total) → arithmetic (Add*, date − date) → formatting (InvariantCulture) → parsing (Parse/TryParse/ParseExact) → comparison + sorting → DateTimeOffset & UTC → Event Scheduler
- Step 131
What a DateTime really is — ticks and Kind
Almost every program eventually has to reason about *when* something happened: when an order was placed, when a session …
Start lesson - Step 132
Creating dates — Now, Today, UtcNow, and constructors
There are two broad ways to obtain a DateTime: ask the system clock for the present moment, or construct an explicit poi…
Start lesson - Step 133
Reading the pieces — Year, Month, DayOfWeek, DayOfYear
Once you hold a DateTime you frequently want to pull individual fields out of it: the year for a report header, the hour…
Start lesson - Step 134
TimeSpan — measuring durations
A DateTime answers "when?"; a TimeSpan answers "how long?". Where DateTime is an absolute point on the timeline, System.…
Start lesson - Step 135
Date arithmetic — adding intervals and subtracting dates
Now that you have both an absolute point (DateTime) and a duration (TimeSpan), you can do the two operations that make d…
Start lesson - Step 136
Formatting dates — standard and custom, always InvariantCulture
Turning a DateTime into text is something every program does — for logs, file names, API payloads, and screens. The meth…
Start lesson - Step 137
Parsing dates — Parse, TryParse, and ParseExact
Parsing is formatting's mirror image: turning text back into a DateTime. It is also where the most painful production bu…
Start lesson - Step 138
Comparing and sorting dates
Because a DateTime is fundamentally a single tick count, comparing two of them is as natural as comparing two numbers. C…
Start lesson - Step 139
DateTimeOffset and why you store UTC
Plain DateTime has a quiet weakness: a value with Kind == Unspecified does not say which time zone it belongs to, and ev…
Start lesson - Step 140
Capstone: build an Event Scheduler
Time to put the whole chapter to work. A scheduler is the canonical date-and-time application: it parses timestamps, mea…
Start lesson
StringBuilder (append/insert, no copies) → Split/Join/Substring/Pad string surgery → StringReader/StringWriter (TextReader/TextWriter) → JSON serialize (System.Text.Json) → Deserialize<T> + case-insensitive → JsonSerializerOptions (camelCase, indented, ignore nulls) → JsonDocument/JsonElement DOM → manual CSV parse + build → MemoryStream + UTF-8 encoding (bytes↔text) → JSON config & order processor capstone
- Step 151
StringBuilder — building text without the waste
You already know that string is immutable: once a string exists on the heap, its characters can never change. Every oper…
Start lesson - Step 152
String surgery — Split, Join, Substring, and friends
Most real-world text processing is a small vocabulary of string methods applied in the right order. Split breaks a strin…
Start lesson - Step 153
TextReader & TextWriter — StringReader and StringWriter
C# models all text input behind one abstract class, TextReader, and all text output behind its mirror, TextWriter. Conso…
Start lesson - Step 154
JSON, part 1 — serializing with System.Text.Json
JSON — JavaScript Object Notation — is the lingua franca of modern data exchange. APIs return it, config files use it, m…
Start lesson - Step 155
JSON, part 2 — deserializing into typed objects
Deserialization is the reverse trip: JSON text in, a C# object out. The method is JsonSerializer.Deserialize<T>(jsonStri…
Start lesson - Step 156
JSON, part 3 — shaping output with JsonSerializerOptions
JsonSerializerOptions is the dial board for both directions of JSON. You met PropertyNameCaseInsensitive for reading; th…
Start lesson - Step 157
JSON, part 4 — the DOM with JsonDocument & JsonElement
Sometimes you don't have — or don't want — a C# type to deserialize into. Maybe the shape is dynamic, you only need one …
Start lesson - Step 158
CSV — parsing and building delimited data by hand
CSV — comma-separated values — is the oldest and most stubborn data format in computing. A spreadsheet, a database expor…
Start lesson - Step 159
Streams & encoding — bytes, text, and MemoryStream
Underneath every text reader and writer lies a Stream — the abstraction for a sequence of BYTES, not characters. Files, …
Start lesson - Step 160
Capstone — JSON config & order processor
Time to put the whole chapter to work. You'll build a small but realistic data processor: it reads a JSON configuration …
Start lesson
Query, project, group, join, and aggregate any collection — and master deferred execution.
- Step 141
LINQ in depth — query syntax vs method syntax
You already met LINQ in passing back in Chapter 7, where Where and Any helped you filter a list. This chapter goes deep.…
Start lesson - Step 142
Filtering with Where
Where is the workhorse of LINQ. It takes a predicate — a function that returns a bool — and yields only the elements for…
Start lesson - Step 143
Projecting with Select, anonymous types, and SelectMany
Where decides which elements survive; Select decides what each surviving element becomes. This operation is called proje…
Start lesson - Step 144
Ordering with OrderBy, OrderByDescending, and ThenBy
OrderBy sorts a sequence by a key you extract from each element. `people.OrderBy(p => p.Age)` arranges people youngest-f…
Start lesson - Step 145
Grouping with GroupBy and IGrouping
GroupBy partitions a sequence into buckets that share a common key. `words.GroupBy(w => w[0])` groups words by their fir…
Start lesson - Step 146
Aggregating with Count, Sum, Min, Max, Average, and Aggregate
Aggregation operators reduce a whole sequence to a single value. The everyday five are Count, Sum, Min, Max, and Average…
Start lesson - Step 147
Joining sequences with Join and GroupJoin
Real data is rarely in one list. You have customers in one collection and their orders in another, linked by a customer …
Start lesson - Step 148
Set operations and partitioning
LINQ ships the classic set operations as operators that compare two sequences. Distinct() removes duplicates within one …
Start lesson - Step 149
Deferred vs immediate execution
Here is the single most important idea in LINQ — and the one that trips up almost everyone at first. Most LINQ operators…
Start lesson - Step 150
Capstone — the sales report engine
Time to put the whole chapter to work. A sales report is the quintessential LINQ task: take raw transaction rows and red…
Start lesson
Run code in parallel without corrupting your data: threads, locks, Interlocked, Tasks, Parallel loops, concurrent collections, coordination primitives, and producer/consumer pipelines.
- Step 171
Threads — running code in parallel
Until now every program you wrote ran on a single thread of execution: one instruction after another, top to bottom, lik…
Start lesson - Step 172
Race conditions — when threads collide
The moment two threads write to the SAME variable without coordination, you have a race condition: a bug whose outcome d…
Start lesson - Step 173
lock and Monitor — mutual exclusion
The lock statement is C#'s everyday tool for mutual exclusion. You write lock (someObject) { ... } and the runtime guara…
Start lesson - Step 174
Interlocked — lock-free atomic operations
Locks are general, but for the most common case — atomically updating a single number — they're heavier than they need t…
Start lesson - Step 175
Task.Run — CPU work without raw threads
Creating a raw Thread is a fairly heavy act: each one consumes about a megabyte of stack and takes real time to spin up …
Start lesson - Step 176
Parallel.For and Parallel.ForEach
Often the work you want to parallelise is simply a loop: do the same independent thing to each item in a range or a coll…
Start lesson - Step 177
Concurrent collections — thread-safe containers
The ordinary collections — List<T>, Dictionary<K,V>, Queue<T> — are NOT thread-safe. If two threads add to the same List…
Start lesson - Step 178
Coordination — CountdownEvent, Barrier, reset events
So far we've protected shared DATA. The other half of concurrency is coordinating TIMING — making one thread wait until …
Start lesson - Step 179
Producer/consumer with BlockingCollection
The producer/consumer pattern is one of the most useful shapes in concurrent programming: one or more PRODUCER threads g…
Start lesson - Step 180
Capstone — the parallel word aggregator
This capstone fuses the whole chapter into one small data-processing engine: a PARALLEL AGGREGATOR. It reads a stream of…
Start lesson
Nullable reference types, the null operators, and the full pattern-matching toolkit — type, property, relational, logical, tuple, list, and positional patterns — culminating in a pattern-driven command interpreter.
- Step 161
Nullable reference types — null as a first-class question
For most of C#'s life, every reference type could quietly be null, and the compiler never warned you. A `string` paramet…
Start lesson - Step 162
Null operators — ?. ?[] ?? and ??=
Once you accept that some values might be null, you need ergonomic tools for working with them — not a forest of `if (x …
Start lesson - Step 163
Pattern matching — the is operator grows up
You already know the `is` operator as a yes/no type test: `obj is string` returns true when `obj` is a string. Modern C#…
Start lesson - Step 164
Switch expressions — patterns as arms
The `switch` STATEMENT you met earlier branches and falls through cases. The `switch` EXPRESSION, added in C# 8, is a di…
Start lesson - Step 165
Property patterns — matching on an object's shape
So far our patterns have inspected a value's TYPE or its identity. Property patterns go one level deeper: they let you m…
Start lesson - Step 166
Relational and logical patterns — ranges and combinators
C# 9 added two families of patterns that turn pattern matching into a concise way to describe RANGES and COMBINATIONS. R…
Start lesson - Step 167
Tuple patterns — switching on several values at once
Sometimes a decision depends on TWO values together, not one. A rock-paper-scissors outcome depends on (yours, theirs). …
Start lesson - Step 168
List patterns — matching the shape of a sequence
C# 11 (shipped with .NET 7, and fully supported on our .NET 8 runner) added list patterns — the ability to match an arra…
Start lesson - Step 169
Positional patterns — deconstructing records in a match
Records and pattern matching were designed for each other. A positional record like `record Point(int X, int Y)` automat…
Start lesson - Step 170
Capstone — a pattern-matching command interpreter
This capstone weaves every thread of the chapter into one small interpreter. You'll read a stream of commands, parse eac…
Start lesson
Build a hand-rolled assertion harness, learn Arrange-Act-Assert and the red-green-refactor cycle, test edge cases and exceptions, isolate units with test doubles, and finish by TDD-ing a Roman-numeral converter behind a mini test runner that tallies the results.
- Step 191
Why test? What automated tests buy you
Every program you have written so far in this course, you have tested — by reading the expected output, running it, and …
Start lesson - Step 192
Your first test — a tiny Check.Equal harness
Writing `expected == actual ? "PASS" : "FAIL"` by hand every time is repetitive, and repetition is where bugs in your TE…
Start lesson - Step 193
Arrange, Act, Assert — the shape of a good test
Every clear test has the same three-beat rhythm: ARRANGE the inputs and objects you need, ACT by calling the one thing y…
Start lesson - Step 194
Red, Green, Refactor — the TDD cycle
Test-Driven Development inverts the usual order: you write the TEST first, watch it fail, then write just enough code to…
Start lesson - Step 195
Testing edge cases — think adversarially
Most bugs do not hide in the middle of the input range — they lurk at the EDGES. The 'happy path' (a normal list, a posi…
Start lesson - Step 196
Testing exceptions — asserting a method throws
A method's contract is not only what it RETURNS for valid input — it is also what it THROWS for invalid input. `Withdraw…
Start lesson - Step 197
Test doubles — fakes and stubs via interfaces
A unit test isolates ONE unit. But real units have collaborators: a billing service that needs a clock, an order process…
Start lesson - Step 198
Parameterized tests — one assertion, a table of cases
When you want to test the SAME behaviour against MANY inputs, copy-pasting an assertion line ten times is wasteful and e…
Start lesson - Step 199
Test organization — naming, focus, independence
A test suite is code, and like all code it can be clean or a mess. Three habits separate maintainable suites from the ki…
Start lesson - Step 200
Capstone — a mini test runner for a Roman-numeral converter
This capstone ties the whole chapter together: you will TDD a small feature behind a hand-rolled test runner that tallie…
Start lesson
Refactor smelly code into clean, flexible designs — guard clauses, Extract Method, and the five SOLID principles, all behaviour-preserving.
- Step 181
What clean code is — and why readability beats cleverness
You have spent eighteen chapters learning what C# can do. This chapter is about something different: how to write code t…
Start lesson - Step 182
Guard clauses — flatten the if-pyramid with early returns
Nested if statements are one of the most common sources of unreadable code. When every step of a method is wrapped insid…
Start lesson - Step 183
Extract Method — decompose a long method into named small ones
Extract Method is the single most useful refactoring in any language. When a method does too much, you find a chunk of l…
Start lesson - Step 184
Single Responsibility — one reason to change
The S in SOLID is the Single Responsibility Principle (SRP): a class or method should have one, and only one, reason to …
Start lesson - Step 185
Open/Closed — extend with polymorphism, don't edit a switch
The O in SOLID is the Open/Closed Principle (OCP): software entities should be open for extension but closed for modific…
Start lesson - Step 186
Liskov Substitution — subtypes must honour the base contract
The L in SOLID is the Liskov Substitution Principle (LSP), named for Barbara Liskov. It says: if S is a subtype of T, th…
Start lesson - Step 187
Interface Segregation — many small interfaces over one fat one
The I in SOLID is the Interface Segregation Principle (ISP): no client should be forced to depend on methods it does not…
Start lesson - Step 188
Dependency Inversion — depend on abstractions, not concretions
The D in SOLID is the Dependency Inversion Principle (DIP): high-level modules should not depend on low-level modules — …
Start lesson - Step 189
Dependency Injection — constructor injection by hand
Dependency Inversion told you to depend on abstractions; Dependency Injection (DI) is the practical technique that suppl…
Start lesson - Step 190
Capstone — refactor a smelly god-method into clean, SOLID code
This capstone brings the whole chapter together. You are handed a single god-method — a tangle of nested ifs, a switch-o…
Start lesson
Measure how code scales: Big-O growth rates, searching and sorting, recursion and memoization, data-structure trade-offs, and time-vs-space — capped by a two-sum workshop comparing naive O(n^2) to optimal O(n).
- Step 201
Big-O — measuring how code scales
Up to now we have judged code mostly by whether it produces the right answer. This chapter adds a second, equally import…
Start lesson - Step 202
O(1) vs O(n) — index versus scan
The two most common complexities you will write are O(1), constant time, and O(n), linear time. Constant time means the …
Start lesson - Step 203
O(log n) and O(n log n) — halving and good sorts
Logarithmic time, O(log n), is what you get when each step throws away a constant FRACTION of the remaining work — almos…
Start lesson - Step 204
O(n^2) and beyond — spotting the slow ones
Quadratic time, O(n²), is the first complexity that genuinely hurts at scale, and it is the easiest to write by accident…
Start lesson - Step 205
Searching — linear versus binary
Searching — finding whether and where a value lives in a collection — is the algorithm you will write most often, so it …
Start lesson - Step 206
Sorting basics — teaching sorts vs the real Array.Sort
Sorting arranges elements into order, and it is worth implementing a simple sort by hand once — not because you will shi…
Start lesson - Step 207
Recursion complexity — recurrences and memoization
Recursion can hide its true cost behind elegant code, so analysing recursive complexity is a skill worth practising. The…
Start lesson - Step 208
Data-structure trade-offs — picking the right container
Choosing the right data structure is often a bigger speed win than any clever algorithm, because it changes the Big-O of…
Start lesson - Step 209
Space complexity — trading memory for time
Big-O measures more than time; it measures MEMORY too. Space complexity counts how much EXTRA memory an algorithm needs …
Start lesson - Step 210
Capstone — two-sum, naive vs optimal
This capstone ties the whole chapter together on one famous problem: TWO-SUM. Given a list of integers and a target, dec…
Start lesson
Stack vs heap, the generational GC, IDisposable, boxing, Span<T>, stackalloc, string allocations, and measuring your way to allocation-light code.
- Step 211
Stack vs heap — where your values actually live
Every running C# program juggles memory in two very different places, and understanding which is which explains most of …
Start lesson - Step 212
The garbage collector — generations and what gets collected
C# is a *managed* language, and the heart of that word is automatic memory management: you allocate with `new`, and you …
Start lesson - Step 213
IDisposable and using — deterministic cleanup
The garbage collector is brilliant at reclaiming *memory*, but memory is not the only resource a program holds. File han…
Start lesson - Step 214
Boxing and unboxing — the hidden heap allocation
Here is a fact that surprises people: in C#, *everything* is compatible with `object`, including an `int`. `object o = 4…
Start lesson - Step 215
Span<T> and ReadOnlySpan<T> — slicing without allocating
Suppose you have an array of a thousand integers and you want to work with just the middle hundred. The obvious move is …
Start lesson - Step 216
stackalloc — scratch buffers with zero heap cost
Sometimes you need a small temporary array — a scratch buffer to build a result, hold intermediate values, or accumulate…
Start lesson - Step 217
String allocations — interning, StringBuilder, span slicing
Strings are the most allocation-heavy type most programs touch, for one fundamental reason: in C# a `string` is *immutab…
Start lesson - Step 218
Struct vs class — the allocation-pressure angle
Chapter 13 introduced `struct` and `class` as a question of *semantics*: value types copy, reference types share. This l…
Start lesson - Step 219
Measuring and avoiding allocations
The cardinal rule of performance work is: *measure, do not guess*. Intuition about what is slow is famously unreliable —…
Start lesson - Step 220
Capstone — the allocation-budget readings analyser
This capstone pulls the whole chapter into one routine. You are handed a line of sensor readings and asked for three sta…
Start lesson
Inspect types at runtime, construct and invoke members dynamically, design custom attributes, and build attribute-driven engines — then make them fast with caching.
- Step 221
Reflection — a program that inspects itself
Up to now your code has always known, at the moment you wrote it, exactly which types it was working with. You typed `ne…
Start lesson - Step 222
Inspecting members — properties, methods, fields, BindingFlags
A `Type` is a catalogue, and the catalogue lists its members. Three methods unlock most inspection work: `GetProperties(…
Start lesson - Step 223
Creating instances at runtime — Activator.CreateInstance
Inspecting a type is only half the story; frameworks also need to BUILD objects of types they were never compiled agains…
Start lesson - Step 224
Invoking members — get/set properties, call methods dynamically
Now we read and write objects whose shape we discovered at runtime. A `PropertyInfo` exposes two workhorse methods: `Get…
Start lesson - Step 225
Custom attributes — attaching your own metadata
Attributes are how you bolt extra metadata onto your code declaratively — the square-bracket annotations you have alread…
Start lesson - Step 226
Reading attributes — turning metadata into behaviour
An attribute that nobody reads is just decoration. The payoff comes when reflection pulls the metadata back out at run t…
Start lesson - Step 227
An attribute-driven validator
Now we assemble the pieces into a feature that feels like a real framework: declarative validation. The idea is the one …
Start lesson - Step 228
Generics and reflection — closing open types at runtime
Generics and reflection meet in a subtle place. A generic type definition like `List<>` with no type argument supplied i…
Start lesson - Step 229
The cost of reflection — and how to cache it away
Reflection is convenient but it is not cheap. Every reflective operation does work a direct call avoids: looking members…
Start lesson - Step 230
Capstone — an attribute-driven mini-serializer
Everything in this chapter converges into one small but genuinely useful engine: a reflective serializer driven by a cus…
Start lesson
Master lazy evaluation: build sequences with yield, compose LINQ-like operators, stream asynchronously, and dodge the deferred-execution traps.
- Step 231
IEnumerable<T>, IEnumerator<T>, and what foreach really does
You have written hundreds of `foreach` loops by now, but you may never have asked what `foreach` actually compiles into.…
Start lesson - Step 232
yield return — lazy sequences and the compiler state machine
Implementing `IEnumerator<T>` by hand — tracking a position field, writing `MoveNext`, exposing `Current`, handling `Dis…
Start lesson - Step 233
yield break, conditional yielding, and early termination
`yield return` produces an element; its companion `yield break;` ends the sequence. Reaching `yield break` makes the con…
Start lesson - Step 234
Infinite generators, Take, and deferred evaluation
Because an iterator computes each element only when asked, it does not need an end. An iterator built around `while (tru…
Start lesson - Step 235
Custom iterators — IEnumerable<T> by hand vs the yield shortcut
To really appreciate `yield`, it helps to write an enumerator the old-fashioned way at least once. Suppose you build a `…
Start lesson - Step 236
Composing iterators — building LINQ-like Map and Filter with yield
Iterators compose. Because every iterator both CONSUMES an `IEnumerable<T>` and PRODUCES an `IEnumerable<T>`, you can ch…
Start lesson - Step 237
Async streams — IAsyncEnumerable<T> and await foreach
Ordinary iterators are synchronous: each `MoveNext()` produces its element right away. But real data often arrives slowl…
Start lesson - Step 238
Batching, paging, and windowing with yield
A whole family of useful operators slices a stream into groups without ever materialising the whole stream. BATCHING (al…
Start lesson - Step 239
Iterator pitfalls — deferred execution, multiple enumeration, side effects
Lazy evaluation is a sharp tool, and the same deferral that makes iterators efficient causes the most common bugs in C# …
Start lesson - Step 240
Capstone — a lazy data-processing pipeline from custom iterators
Time to assemble the whole chapter into one lazy pipeline. You will read a stream of integers, push them through a chain…
Start lesson
Pure functions, first-class lambdas, composition, immutability, Result/Option, pattern matching, and LINQ as a functional toolkit.
- Step 241
The functional mindset — pure functions and referential transparency
Functional programming (FP) is less a feature you switch on and more a way of thinking about your code. The central idea…
Start lesson - Step 242
Functions as values — Func, Action, and first-class functions
The first concrete shift toward FP is treating functions as ordinary values. In C# you can store a function in a variabl…
Start lesson - Step 243
Higher-order functions — map, filter, and reduce
A higher-order function is one that takes a function as an argument, returns a function, or both. Once functions are val…
Start lesson - Step 244
Composition and currying — building functions from functions
Once functions are values, you can build BIGGER functions out of smaller ones without ever calling them. Function compos…
Start lesson - Step 245
Immutability in practice — readonly, records, and with
Pure functions need immutable data to thrive. If the values flowing through your pipeline can be mutated behind your bac…
Start lesson - Step 246
Expression-bodied style — concise functional members
Functional code leans on expressions rather than statements. An expression PRODUCES a value (2 + 3, name.ToUpper(), x > …
Start lesson - Step 247
Result and Option — modelling success and failure as values
Exceptions are the imperative way to signal failure: you throw, and control jumps somewhere up the stack. Functional pro…
Start lesson - Step 248
Functional pattern matching — switch expressions as dispatch
Pattern matching is functional programming's dispatch mechanism — the way a single value gets routed to different handli…
Start lesson - Step 249
LINQ as a functional toolkit — composable, deferred pipelines
LINQ is C#'s functional standard library hiding in plain sight. Every operator you learned in Chapter 15 — Where, Select…
Start lesson - Step 250
Capstone — a functional parse, validate, transform pipeline
This capstone fuses the whole chapter into one program: a railway-oriented pipeline that PARSES, VALIDATES, and TRANSFOR…
Start lesson
Take control of what 'the same' and 'comes first' mean: ==, Equals/GetHashCode, IEquatable, IComparable, comparers, record equality, and the pitfalls that bite.
- Step 251
Equality — == vs .Equals, reference vs value
Asking "are these two things equal?" sounds trivial until you realise C# has two completely different answers depending …
Start lesson - Step 252
Overriding Equals and GetHashCode together
When the default identity equality is wrong for your type, you change it by overriding object.Equals. You cast the incom…
Start lesson - Step 253
IEquatable<T> — typed, boxing-free equality
Overriding object.Equals(object) works, but its signature has a cost: it takes object, so every comparison forces the ru…
Start lesson - Step 254
IComparable<T> — natural ordering and the sign contract
Equality answers "are these the same?" Ordering answers "which one comes first?" A type expresses its natural, built-in …
Start lesson - Step 255
IComparer<T> — external and multiple sort strategies
IComparable<T> bakes ONE natural order into a type. But real data rarely has a single right order: people can sort by ag…
Start lesson - Step 256
Sorting — Array.Sort, List.Sort, OrderBy, ThenBy
C# offers two families of sorting, and knowing when to reach for each saves you grief. Array.Sort and List<T>.Sort sort …
Start lesson - Step 257
IEqualityComparer<T> — custom keys for sets and maps
Just as IComparer<T> externalises ordering, IEqualityComparer<T> externalises equality. It bundles BOTH halves of the ha…
Start lesson - Step 258
Record and struct equality — value semantics for free
Everything in the last several lessons — overriding Equals, implementing IEquatable<T>, computing a consistent GetHashCo…
Start lesson - Step 259
Equality pitfalls — mutable keys, mismatches, floats
The most dangerous equality bug is the MUTABLE KEY. You insert an object into a Dictionary or HashSet, then later mutate…
Start lesson - Step 260
Capstone — a sorted, de-duplicated catalogue
This capstone fuses the whole chapter into one pipeline: a domain type with FULL value equality drives a collection that…
Start lesson
CultureInfo, number/date/currency format strings, culture-aware parsing and string operations, IFormattable, and the always-InvariantCulture-for-machine-data rule.
- Step 261
CultureInfo — why the same value prints differently
A number like one and a half million is not written the same way everywhere on Earth. An American writes 1,500,000.50 — …
Start lesson - Step 262
Number format strings — standard and custom
Once you can pass a culture, the next question is WHAT shape you want the digits in. C# answers with format strings — sh…
Start lesson - Step 263
Currency and percent — the C and P specifiers
Two standard specifiers are so common they get their own letters: C for currency and P for percent. Both are deeply cult…
Start lesson - Step 264
Date and time format strings
Dates are even more culture-sensitive than numbers, because the very ORDER of the components changes: Americans write mo…
Start lesson - Step 265
Parsing with NumberStyles, DateTimeStyles, and culture
Formatting turns a value into text; parsing turns text back into a value. Both must agree on the culture, or the round-t…
Start lesson - Step 266
Composite formatting, alignment, and interpolation
So far we have formatted single values. Composite formatting assembles several into one string with placeholders. The cl…
Start lesson - Step 267
IFormattable — teaching your own type to format
Every built-in numeric and date type understands format strings because it implements the IFormattable interface — a sin…
Start lesson - Step 268
Culture-aware string operations and StringComparison
Formatting is not the only place culture sneaks in. Comparing, sorting, upper-casing, and lower-casing strings can ALL d…
Start lesson - Step 269
Globalization pitfalls — the Turkish-I and friends
Globalization bugs share a signature: the code works perfectly on the developer's machine and fails mysteriously somewhe…
Start lesson - Step 270
Capstone — a deterministic culture-aware report formatter
Time to pull the chapter together into one tool: a report formatter that reads line items and prints a tidy, aligned fin…
Start lesson
Integer ranges and silent overflow, checked vs unchecked, floating-point reality, decimal money, rounding strategies, the Math class, bit operations, BigInteger, and robust parsing.
- Step 271
The integer family — ranges, MinValue/MaxValue, and silent overflow
You have been writing `int` since the first chapter, but C# offers a whole family of integer types and each one trades r…
Start lesson - Step 272
checked and unchecked — choosing what overflow does
The previous lesson left us with a worrying fact: integer arithmetic overflows silently by default. C# gives you two key…
Start lesson - Step 273
Floating point reality — why 0.1 + 0.2 isn't 0.3
Integers are exact. Floating-point numbers — `float` (32-bit, ~7 significant digits) and `double` (64-bit, ~15-17 signif…
Start lesson - Step 274
decimal — the type built for money
If `double` cannot represent 0.1 exactly, you must never use it for money. A cent that drifts by `0.00000001` per operat…
Start lesson - Step 275
Rounding — Math.Round, midpoint strategies, Floor/Ceiling/Truncate
Rounding sounds trivial until you ask: what does 2.5 round to? Most people say 3, but C#'s `Math.Round(2.5)` returns 2. …
Start lesson - Step 276
The Math class — Pow, Sqrt, Abs, Clamp, and integer division
The `System.Math` static class is C#'s toolbox of numeric functions. Everything on it is a `static` method, so you call …
Start lesson - Step 277
Bit operations — &, |, ^, ~, shifts, flags, and hex/binary literals
Underneath every integer is a row of bits, and C# lets you operate on those bits directly. The bitwise operators are `&`…
Start lesson - Step 278
BigInteger — arbitrary precision when long isn't enough
Even `long`, with its 9.2-quintillion ceiling, runs out eventually. The factorial of 21 already overflows a `long`; cryp…
Start lesson - Step 279
Parsing and converting — Parse, TryParse, Convert, and base conversion
Input arrives as text — from the console, a file, an HTTP request — and you must turn that text into numbers before you …
Start lesson - Step 280
Capstone — a precision calculator
Time to assemble the chapter into one small but disciplined tool: a precision calculator that picks the *right* numeric …
Start lesson
Beyond List and Dictionary: stacks, queues, linked lists, sorted and priority collections, read-only views, immutability, and how to choose the right container.
- Step 281
The collections landscape — choosing a container
Back in Chapter 7 you met the three workhorses of C# collections: List<T> for an ordered, growable sequence; Dictionary<…
Start lesson - Step 282
Stack<T> and Queue<T> — LIFO and FIFO
Two of the most useful collections model how items leave as much as how they arrive. A Stack<T> is Last-In-First-Out (LI…
Start lesson - Step 283
LinkedList<T> — nodes and O(1) splicing
A List<T> stores its elements in one contiguous block of memory. That makes indexing instant but insertion in the middle…
Start lesson - Step 284
SortedDictionary<K,V> and SortedSet<T> — always in order
Dictionary<K,V> and HashSet<T> are built on hashing, which gives O(1) average lookup but no inherent order — iterating t…
Start lesson - Step 285
PriorityQueue<TElement,TPriority> — urgency first
A plain Queue<T> serves items strictly in arrival order. But real schedulers care about urgency, not arrival: an ER tria…
Start lesson - Step 286
Dictionary in depth — internals, init, GroupBy, ToLookup
Dictionary<K,V> is the most-used keyed collection in .NET, so it pays to understand how it works. Internally it's a hash…
Start lesson - Step 287
Read-only views — exposing collections safely
Encapsulation (Chapter 5) says a class controls its own state. But collections leak that control quietly. If a class has…
Start lesson - Step 288
Immutable collections — never change after construction
A read-only VIEW (last lesson) stops a caller from mutating a collection through one reference, but the underlying List<…
Start lesson - Step 289
Choosing a collection — a decision guide
You now know the whole family, so the real skill is selection. The single best question is: what operations will I do MO…
Start lesson - Step 290
Capstone — a task scheduler with the right collections
Time to put the whole family to work. You'll build a small TASK SCHEDULER that processes a stream of commands, and the o…
Start lesson
The classic Gang of Four patterns retold in idiomatic modern C#: Strategy, Factory, Builder, Singleton, Observer, Decorator, Adapter, and Command — with Func/Action over interface ceremony, and the wisdom to know when NOT to use them.
- Step 291
What design patterns are — and when NOT to reach for them
A design pattern is a named, repeatable solution to a problem that keeps showing up in object-oriented code. They were c…
Start lesson - Step 292
Strategy — pluggable behaviour, interface or Func<>
The Strategy pattern lets you select an algorithm at runtime by treating the algorithm itself as an object you can swap …
Start lesson - Step 293
Factory Method — centralise creation, return by abstraction
A Factory is any piece of code whose job is to *create objects* so that the rest of the program doesn't have to know whi…
Start lesson - Step 294
Builder — step-by-step construction and fluent config
The Builder pattern separates *how* an object is assembled from the object's own representation, so the same constructio…
Start lesson - Step 295
Singleton — one instance done right, and why DI is usually better
The Singleton pattern guarantees a class has exactly one instance and gives the whole program a single global access poi…
Start lesson - Step 296
Observer — publish/subscribe, and C# events are the GoF Observer
The Observer pattern lets one object (the *subject* or *publisher*) notify a changing set of dependent objects (the *obs…
Start lesson - Step 297
Decorator — wrap an object to add behaviour, then compose layers
The Decorator pattern adds responsibilities to an object by *wrapping* it in another object that shares the same interfa…
Start lesson - Step 298
Adapter — make an incompatible interface fit
The Adapter pattern wraps an object with an interface your code *can't use* in a thin shim that exposes the interface it…
Start lesson - Step 299
Command — an action as an object (undo, queues, history)
The Command pattern turns *a request to do something* into a first-class object: the action, its parameters, and (option…
Start lesson - Step 300
Capstone — a text-processing pipeline that composes four patterns
Patterns rarely appear alone — real designs *compose* them, each solving the slice of the problem it fits best. This cap…
Start lesson
Build a working expression interpreter — tokenizer, recursive-descent parser, AST, and a variable-aware calculator language.
- Step 301
What an interpreter is — the tokens → AST → value pipeline
An interpreter is a program that reads another program and runs it. In this chapter we'll build a small but complete one…
Start lesson - Step 302
Tokenizing — turning a string into a list of tokens
The first stage of any interpreter is the TOKENIZER (or lexer). Its job is small and well-defined: scan the raw characte…
Start lesson - Step 303
Grammar and precedence — why * binds tighter than +
A list of tokens is not yet a meaningful expression — we still have to decide how they GROUP. Is 2 + 3 * 4 read as (2 + …
Start lesson - Step 304
A recursive-descent parser — code that mirrors the grammar
A recursive-descent parser is the most direct way to turn a grammar into code: you write ONE method per grammar rule, an…
Start lesson - Step 305
AST nodes — a sealed record hierarchy for the tree
So far the parser computed a double directly. Now we separate STRUCTURE from VALUE: the parser will build a tree of node…
Start lesson - Step 306
Evaluating the AST — walking the tree with pattern matching
We have a tree of nodes; now we compute its value. The evaluator is a single recursive function — call it Eval — that ta…
Start lesson - Step 307
Variables and the environment — a Dictionary of names to values
A calculator that can only crunch constants is a glorified arithmetic engine. The leap to a real little LANGUAGE comes w…
Start lesson - Step 308
Parser error handling — clear messages for broken input
Real input is messy. Users type `(4 + 1` and forget the close paren, write `3 +` and stop, or hand you `2 3` with no ope…
Start lesson - Step 309
Extending the language — unary minus and built-in functions
A well-structured interpreter is a joy to GROW. Because the stages are separate and the parser mirrors the grammar, addi…
Start lesson - Step 310
Capstone — a full calculator interpreter with variables
Time to assemble the whole chapter into one working interpreter. The capstone is a CALCULATOR LANGUAGE: a program is a s…
Start lesson
Variance, advanced constraints, generic math (INumber<T>), static abstract members, and IParsable<T> — the deep machinery behind reusable, type-safe code.
- Step 311
Generics, the deep version — open vs closed types
Chapter 9 introduced generics as the answer to "how do I write a List that works for any element type without copy-pasti…
Start lesson - Step 312
Covariance — when IEnumerable<Cat> is an IEnumerable<Animal>
Here is a question that trips up almost everyone the first time: if `Cat` derives from `Animal`, is a `List<Cat>` also a…
Start lesson - Step 313
Contravariance — when Action<Animal> is an Action<Cat>
Covariance flowed in the direction your intuition expected: a sequence of cats is a sequence of animals. Contravariance …
Start lesson - Step 314
Advanced constraints — combining and depending
A single constraint like `where T : IComparable<T>` unlocks one ability. Real generic code often needs several abilities…
Start lesson - Step 315
Generic math — INumber<T> and one Sum to rule them all
For two decades C# had an embarrassing gap: you could not write a single generic method that adds numbers. `T Add<T>(T a…
Start lesson - Step 316
Static abstract interface members — the engine behind generic math
How does `T.Zero` even work? `Zero` is a STATIC member, and before C# 11 an interface could only declare instance member…
Start lesson - Step 317
IParsable<T> — generic parsing and the T.Parse pattern
Parsing text into a value is everywhere — reading config, CSV columns, command arguments, network payloads. For years ea…
Start lesson - Step 318
Generic delegates and type inference
Generics and delegates were made for each other. `Func<TIn, TResult>` and `Action<T>` are themselves generic delegate ty…
Start lesson - Step 319
Generic pitfalls — default(T), boxing, and over-genericizing
Generics are powerful, but a handful of traps recur often enough to deserve their own lesson. The first is `default(T)`.…
Start lesson - Step 320
Capstone — a generic numeric Stats<T> aggregator
Time to fuse the whole chapter into one type. The capstone builds `Stats<T> where T : INumber<T>` — a generic, constrain…
Start lesson
what an FSM is (states/events/transitions) → enum + switch transition function → data-driven Dictionary<(State,Event),State> tables → guarded transitions + side-effect actions → rejecting illegal events → states as a sealed record hierarchy → entry/exit hooks + transition logging → hierarchical states + history → FSM pitfalls (state explosion, boolean soup, missing transitions) → order workflow engine capstone
- Step 321
What is a finite state machine?
A finite state machine (FSM, or just "state machine") is one of the oldest and most useful ideas in computing, and the g…
Start lesson - Step 322
The simplest FSM — an enum and a switch
Using bare strings for states, as we did in the previous lesson, works but is fragile: a typo like `"Greeen"` compiles f…
Start lesson - Step 323
Data-driven transition tables
A `switch` is code; a transition TABLE is data. As a machine grows past a handful of transitions, the switch starts to s…
Start lesson - Step 324
Guarded transitions and side-effect actions
So far a transition has depended only on the current state and the event. But real machines often need a CONDITION too: …
Start lesson - Step 325
Rejecting illegal events
Up to now our catch-all has quietly done nothing on unknown (state, event) pairs. That "silently ignore" policy is somet…
Start lesson - Step 326
States as a sealed record hierarchy
An enum names states beautifully but it cannot carry data. A Connecting state might want to remember how many attempts i…
Start lesson - Step 327
Entry, exit, and transition hooks
Once a machine has interesting states, you frequently want something to happen whenever you ENTER a state or whenever yo…
Start lesson - Step 328
Hierarchical states and history
Flat state machines explode when several states share common behaviour. Imagine a Pomodoro-style timer that is either Wo…
Start lesson - Step 329
Pitfalls — when an FSM helps and when it hurts
State machines are not free, and reaching for one reflexively is its own mistake. The most common trap is STATE EXPLOSIO…
Start lesson - Step 330
Capstone — an order workflow engine
Time to assemble everything this chapter taught into one small workflow engine. You will build an order-processing FSM t…
Start lesson
Model the domain with types so illegal states are unrepresentable
- Step 331
Modeling the domain, not the database
Most bugs are not typos or off-by-one slips — they are the program quietly doing the wrong thing with data that should n…
Start lesson - Step 332
Value objects — equality by content
A *value object* is a small, immutable type that has no identity of its own — it is defined entirely by the values it ho…
Start lesson - Step 333
Entities vs value objects — identity vs content
The most important modeling decision you make for any concept is: does it have *identity*, or is it defined purely by it…
Start lesson - Step 334
Making illegal states unrepresentable
The central technique of this chapter has a memorable name: *make illegal states unrepresentable*. Instead of constructi…
Start lesson - Step 335
Smart constructors — validate on creation
A *smart constructor* is the mechanism that turns "illegal states unrepresentable" from an aspiration into a guarantee. …
Start lesson - Step 336
Invariants and encapsulation
An *invariant* is a rule that must hold true for an object's entire lifetime: an account balance never drops below zero,…
Start lesson - Step 337
Closed sets — enums vs sealed hierarchies
Many domain concepts are a *closed set of choices*: a traffic light is Red, Amber, or Green; a payment is by Card, Cash,…
Start lesson - Step 338
Aggregates and the consistency boundary
As models grow, objects start to cluster: an `Order` owns its `LineItem`s; a `Cart` owns its entries; an `Invoice` owns …
Start lesson - Step 339
Domain events — recording what happened
So far our models capture the *current state* of the domain. But the business often cares just as much about *what happe…
Start lesson - Step 340
Capstone — model a small Order domain
This capstone weaves every thread of the chapter into one small, trustworthy domain. You will model a shopping cart / or…
Start lesson
the request pipeline → Minimal APIs → routing & parameter binding → dependency injection & service lifetimes → middleware → model binding & validation → controllers vs minimal → status codes, results & ProblemDetails → configuration & auth basics → Catalog Web API capstone
- Step 341
ASP.NET Core — what a web framework actually does
Everything you have learned so far runs in a console: a process starts, your code runs top to bottom, it prints, it exit…
Start lesson - Step 342
Minimal APIs — endpoints as lambdas
A Minimal API endpoint is a route paired with a handler. The handler is just a delegate — usually a lambda — and the fra…
Start lesson - Step 343
Routing & parameter binding
Routing is the process of matching an incoming request's method and path to exactly one endpoint. A route template like …
Start lesson - Step 344
Dependency injection & service lifetimes
Dependency injection (DI) is the backbone of ASP.NET Core. Instead of a class reaching out to construct the things it ne…
Start lesson - Step 345
The middleware pipeline
Every request flows through a pipeline of middleware before reaching your endpoint, and back out through the same compon…
Start lesson - Step 346
Model binding & validation
You saw binding pull simple values from the route and query string. The richer case is binding a whole object from the r…
Start lesson - Step 347
Controllers — the class-based alternative
Before Minimal APIs, every ASP.NET Core endpoint lived in a controller — a class that groups related actions as methods.…
Start lesson - Step 348
Status codes, results & ProblemDetails
The HTTP status code is the first thing a client reads, and choosing it correctly is the difference between an API other…
Start lesson - Step 349
Configuration & authentication basics
A real service needs settings that change between environments — a connection string, an API key, a feature toggle — wit…
Start lesson - Step 350
Capstone — a complete Catalog Web API
This capstone assembles the whole chapter into one coherent service: an in-memory product catalog with full CRUD, depend…
Start lesson
what an ORM is → DbContext & entities → configuring the model (annotations vs Fluent API) → migrations → querying with LINQ (IQueryable → SQL) → CRUD & the change tracker → relationships → loading related data (Include / N+1) → tracking & performance → data-model capstone
- Step 351
Entity Framework Core — what an ORM actually does
Your code thinks in objects: a Product has a Name, a Price, and a list of Reviews, and a Review points back at its Produ…
Start lesson - Step 352
DbContext & entities — the session and the tables
The center of every EF Core application is the DbContext. It is two things at once. First, it is a session — a short-liv…
Start lesson - Step 353
Configuring the model — annotations vs Fluent API
Conventions get you most of the way, but real schemas need precision: a column should be NVARCHAR(100), not unbounded; a…
Start lesson - Step 354
Migrations — evolving the schema safely
Code-first means your C# model is the source of truth, but the database needs an actual schema — tables, columns, indexe…
Start lesson - Step 355
Querying with LINQ-to-Entities
You already know LINQ from the collections chapter. EF Core lets you write the same Where, OrderBy, Select, GroupBy quer…
Start lesson - Step 356
CRUD & the change tracker
Reading is half the story; the other half is writing. EF Core's writing model is built on the change tracker, and once y…
Start lesson - Step 357
Relationships — one-to-many, one-to-one, many-to-many
Real data is connected: a Blog has many Posts, a Post has many Comments, a User has one Profile, a Post has many Tags an…
Start lesson - Step 358
Loading related data & the N+1 problem
You have navigation properties; now the question is when their data is actually loaded from the database. A query for bl…
Start lesson - Step 359
Tracking, projection & performance
By default, every entity a query returns is tracked: the DbContext keeps a reference to it and a snapshot of its origina…
Start lesson - Step 360
Capstone — a Blog/Post/Comment data model end to end
This capstone assembles the whole chapter into one coherent data model: a blogging schema with Blogs, Posts, and Comment…
Start lesson
the Generic Host → configuration & the Options pattern → logging (ILogger) → background services → IHttpClientFactory → resilience (retries, circuit breaker, timeout) → gRPC → real-time SignalR → messaging & queues → resilient worker service capstone
- Step 361
The Generic Host — one bootstrap to rule them all
Every non-trivial .NET application — a web API, a console worker, a desktop app that needs background services — shares …
Start lesson - Step 362
Configuration providers & the Options pattern
A deployable service must change behavior between environments — a connection string, a queue name, a retry count, a fea…
Start lesson - Step 363
Logging with ILogger<T> & structured logs
In a console app you reach for Console.WriteLine; in a service you must not. A running service is observed from the outs…
Start lesson - Step 364
Background services & the ExecuteAsync loop
A background service is work that runs for the lifetime of the application, independent of any single request: polling a…
Start lesson - Step 365
IHttpClientFactory — calling other services right
A distributed system is mostly services calling other services over HTTP, and HttpClient is how C# makes those calls. It…
Start lesson - Step 366
Resilience — retries, backoff & circuit breakers
In a distributed system, failure is not an exception — it is the normal weather. A network packet drops, a database brie…
Start lesson - Step 367
gRPC — strongly-typed service contracts
REST over JSON is the lingua franca of public web APIs, but for service-to-service calls inside a system there is often …
Start lesson - Step 368
SignalR — real-time server-to-client push
Most of the web is request/response: the client asks, the server answers, the connection closes. But some features need …
Start lesson - Step 369
Async messaging — queues, topics & idempotency
Direct calls — HTTP, gRPC — couple two services in time: the caller waits for the callee, and if the callee is down or s…
Start lesson - Step 370
Capstone — a resilient distributed Worker Service
This capstone assembles the whole chapter — and much of the course — into one coherent system: a Worker Service that con…
Start lesson
what Blazor is → Razor components → data binding (@bind) → event handling (EventCallback) → component lifecycle → rendering & state → forms & validation → render models (Server / WebAssembly / Auto) → JavaScript interop → interactive component capstone
- Step 371
Blazor — what it is and where it fits
For decades, building an interactive web page meant writing the back end in one language and the front end in JavaScript…
Start lesson - Step 372
Razor components — markup, @code, and parameters
A Razor component is a reusable unit of UI, and its anatomy is simple: a .razor file containing HTML-like markup interle…
Start lesson - Step 373
Data binding — one-way render and two-way @bind
Binding connects your component's C# state to what the user sees and types. The simplest direction is one-way: you rende…
Start lesson - Step 374
Event handling & EventCallback
Interactivity means responding to what the user does, and in Blazor every DOM event maps to an @-prefixed attribute you …
Start lesson - Step 375
The component lifecycle
Every component goes through a predictable sequence of lifecycle events from the moment Blazor creates it to the moment …
Start lesson - Step 376
Rendering, the render tree & sharing state
When a Blazor component renders, it does not throw away the page and rebuild it. It produces a render tree — a lightweig…
Start lesson - Step 377
Forms & validation
Forms are where most real interactivity lives, and Blazor has a dedicated component for them: EditForm. Instead of wirin…
Start lesson - Step 378
Render models — Server, WebAssembly & Auto
You have built components without worrying where they run; now it is time to choose. Blazor's three interactive render m…
Start lesson - Step 379
JavaScript interop
Blazor lets you write nearly all of your UI in C#, but the browser's own capabilities — local storage, the clipboard, th…
Start lesson - Step 380
Capstone — an interactive Todo dashboard
This capstone assembles the whole chapter into one coherent feature: an interactive Todo dashboard built from composed c…
Start lesson
what WPF is → XAML fundamentals → layout panels → controls & the content model → dependency properties → data binding + INotifyPropertyChanged → the MVVM pattern → ICommand / RelayCommand → ObservableCollection & templates → MVVM app capstone
- Step 381
WPF — what a desktop UI framework actually does
Everything you have built so far either ran in a console or served HTTP from a server. A desktop application is a third …
Start lesson - Step 382
XAML — markup that is really an object graph
XAML (Extensible Application Markup Language, pronounced "zammel") looks like HTML but it is something more precise: it …
Start lesson - Step 383
Layout — the measure/arrange system and the panels
WPF does not place controls at fixed pixel coordinates the way old toolkits did. Instead it runs a two-pass layout algor…
Start lesson - Step 384
Controls, content & templates
WPF controls are built around a content model that is far more flexible than older toolkits, and grasping it unlocks mos…
Start lesson - Step 385
Dependency properties — the property system behind WPF
Almost every property you set in XAML — Width, Background, Text, IsEnabled — is not an ordinary C# property with a priva…
Start lesson - Step 386
Data binding — keeping the UI and your data in sync
Data binding is the feature that makes WPF worth using, and it is the engine that MVVM rides on. A binding is a live lin…
Start lesson - Step 387
MVVM — the architecture that organizes a WPF app
MVVM — Model-View-ViewModel — is the architectural pattern that WPF was designed for, and it falls out almost inevitably…
Start lesson - Step 388
Commands — exposing actions the MVVM way
Binding handles data — a property in, a property out — but an application also has actions: Save, Delete, Refresh, Submi…
Start lesson - Step 389
Observable collections — lists that keep the UI live
A view model that shows a list — contacts, orders, search results — needs to expose that list to an ItemsControl (a List…
Start lesson - Step 390
Capstone — a complete MVVM contact editor
This capstone assembles the whole chapter into one coherent application: a small contact editor that lets you add contac…
Start lesson
what Unity is → the MonoBehaviour lifecycle → GameObjects & components → vectors & transforms → input handling → physics & collisions → prefabs & instantiation → Time.deltaTime & movement → game state & UI → arcade-game capstone
- Step 391
Unity — what a game engine actually gives you
Everything you have built so far either ran top to bottom and exited (a console app) or woke up to answer a request and …
Start lesson - Step 392
The MonoBehaviour lifecycle — when your code runs
A MonoBehaviour is not driven by you calling its methods — it is driven by Unity calling yours, at precise moments, in a…
Start lesson - Step 393
GameObjects & Components — composition in practice
Now that you know a GameObject is a bag of Components, the day-to-day skill is reaching between them: from your script, …
Start lesson - Step 394
Vectors & Transforms — the math of moving things
Position, direction, velocity, and force are all the same kind of thing in a game: a vector. Unity's Vector3 is a struct…
Start lesson - Step 395
Reading input — turning keys into movement
A game is a conversation: the player presses, the game responds, every frame. Reading that input is the bridge between t…
Start lesson - Step 396
Physics & collision — Rigidbodies and Colliders
Up to now you moved objects by writing transform.position directly — teleporting them. That is fine for things that igno…
Start lesson - Step 397
Prefabs & instantiation — spawning at runtime
Most games create objects while they run: a gun fires bullets, a spawner releases enemies, an explosion throws debris. Y…
Start lesson - Step 398
Time & movement — frame-rate independence
Here is the single most important number in real-time game programming: Time.deltaTime, the number of seconds that elaps…
Start lesson - Step 399
Game state, UI & scene management
A game is more than a moving character — it is a system with modes. The main menu is a different world from active play,…
Start lesson - Step 400
Capstone — wiring a small arcade game loop
This final lesson assembles the entire chapter into the shape of a real, if tiny, arcade game — and, because it is the l…
Start lesson