C# for beginners — Mission
Sections
Reading settings
No voice for this language in this browser.
More voices
Code and English terms
Off: the page’s voice reads everything, with no pause between two voices.
No voice for this language in this browser.
More voices
More voices: Microsoft Edge has natural online voices, and Windows (Settings › Time & language › Speech), macOS and Android install others.
Why this course
Section titled “Why this course”The other language courses on this site assume you already write C# or Java. This one doesn’t. It is for someone who has never programmed, or who has written a little Python, JavaScript or spreadsheet formulas, and wants to learn C# properly.
C# is a good first language: the compiler checks your program before it runs and explains what is wrong, the tools are free on Windows, Linux and macOS, and the same language builds command-line tools, web sites, games and desktop applications. The course uses the current versions: C# 14 and .NET 10, released in November 2025.
How the lessons work
Section titled “How the lessons work”Each lesson introduces a few notions, and for each one:
- the idea, in plain words;
- a short program that uses it, with the output it really printed;
- the mistakes beginners make with it, with the exact message of the compiler;
- exercises, with a solution hidden under Solution: try first, then open it.
The examples use small, real data where it helps: the notes of a guitar, the tuning that Guitar Alchemist uses, the names of its projects. You don’t need to play music to follow them.
By the end of this course, I will be able to
Section titled “By the end of this course, I will be able to”- install the .NET SDK, run a C# file and create a project, on Windows, Linux or macOS;
- read a compiler error and fix it;
- store values in variables of the right type, convert between types, and read input from the keyboard;
- make decisions with
ifandswitch, and repeat work with loops; - split a program into methods, and work with arrays and lists;
- model my own data with classes and records, and handle errors with exceptions;
- read and write files, test my code, and use a NuGet package.
Outline
Section titled “Outline”| # | Lesson | Notions |
|---|---|---|
| 1 | Install .NET and run your first program | SDK, dotnet run app.cs, statements, projects, compiler errors |
| 2 | Variables, types and input | int, double, decimal, string, bool, var, conversions, interpolation, Console.ReadLine |
| 3 | Conditions and loops | if, switch, for, foreach, while, break, the debugger |
| 4 | Methods, arrays and lists | parameters, return values, arrays, List<T>, first steps with null |
| 5 | Classes and objects | fields, properties, constructors, methods, static |
| 6 | Records, structs and enums | value and reference types, equality, enum |
| 7 | Interfaces and inheritance | interface, abstract, override, polymorphism |
| 8 | Exceptions and null safety | try/catch/finally, throw, nullable reference types |
| 9 | Collections and LINQ | Dictionary<TKey, TValue>, HashSet<T>, Where, Select, OrderBy |
| 10 | Files and text | File, Path, reading a CSV file of Guitar Alchemist’s projects |
| 11 | Unit tests | xUnit, dotnet test, testing the methods of earlier lessons |
| 12 | A small project | a solution with a library, a console app and tests, a NuGet package, a first look at async |
| — | Journal |
Highlights from the journal
Section titled “Highlights from the journal”The journal records what writing and testing this course turned up. These are the findings that change how you write or run a program; each row links to the lesson that teaches it and to the journal entry with the measurement.
| What the journal found | Why it matters | See |
|---|---|---|
A misspelled Writeline (CS0117) is reported only once the missing ; and quote of the same program are fixed: syntax errors hide the others |
Fixing an error can make new ones appear; that is progress, not a step back | Lesson 1, journal |
double.TryParse("1.5") depends on the culture: true and 15 in es-ES, where the dot separates thousands, false in fr-FR |
The same program reads a different number on a Spanish or a French machine | Lesson 2, journal |
Warnings are printed only when the SDK compiles: a second dotnet run of an unchanged file prints none, even with --no-cache; dotnet clean brings them back |
A warning that is gone on the next run has not been fixed | Lesson 3, journal |
The literal 0 converts to an enum without a cast, and CS8524 warns about a switch expression that has an arm for every name |
An enum variable can hold a number that has no name: the lesson’s program fails on 7 | Lesson 6, journal |
A draft said that shape[i].Fret += 2 on a list of readonly record struct gives CS1612; a probe compiled before publishing gave CS8852 |
Every output and error message in the course is pasted from a run, never written from memory | Lesson 6, journal |
In Guitar Alchemist, ChordTemplate’s ToString() => Name is not sealed, so its derived records print all their properties instead of the chord’s name |
The override of lesson 7 meets the records of lesson 6 in real code; one GA call site logs the dump. Not reported to GA yet |
Lesson 7, QA table |
A nullable warning points where null gets in, not where the program crashes: CS8618 sits on the property’s declaration, and the line that crashes has no warning |
Fix each warning where it is, even far from the crash | Lesson 8, journal |
Guitar Alchemist silences fifteen nullable warnings in NoWarn, twice. Its code has none to hide, but a test file with seven nullable mistakes compiled without a warning |
Silencing a warning also silences the mistakes still to come. Not reported to GA yet | Lesson 8, QA table |
A dictionary’s foreach follows the order of addition only until the first Remove: a key added afterwards takes the removed key’s place |
A sorted result put in a Dictionary stays sorted by chance; sort when the order matters |
Lesson 9, journal |
| Three of the four YAML files that Guitar Alchemist’s music knowledge services read don’t load; each loader catches the exception and carries on with one default item | A catch that only prints hides the bug: GA counts 16 artists, and nothing fails. Reported as GA issue #797; fix proposed in GA PR #808 |
Lesson 9, QA table |
A relative path starts from the current directory, not from the program’s file: l10_where.cs finds data/ga-projects.csv when dotnet run starts in code/csharp-beginner, and misses it from the repository root |
The same program finds its file or not depending on the folder it is started from; a path built from EntryPointFileDirectoryPath works from both |
Lesson 10, journal |
The format string that Guitar Alchemist writes its naturalness CSV with follows the machine’s culture: under fr-FR, 2.50 becomes 2,50, and a row of 6 values splits into 8 |
A file written on a French machine doesn’t read back with Split(','); write numbers with CultureInfo.InvariantCulture. Fix proposed in GA PR #811 |
Lesson 10, QA table |
| Guitar Alchemist’s tests of its YAML services pass while three of the four files don’t load: three tests are skipped, and the others check “more than zero”, which the one default item satisfies | A test that only checks “more than zero” can’t see a fallback; check the real value. Fix proposed in GA PR #808 | Lesson 11, QA table |
With its arguments swapped, Assert.Equal calls the method’s result “Expected” and the test’s value “Actual”; the analyzer rule xUnit2000 warns before the tests run |
The expected value comes first; read the warnings of a test build too | Lesson 11, journal |
dotnet test in a solution’s folder builds only the test projects and what they reference: with a compile error in the console app, the tests still pass and exit with 0 |
Run dotnet build too before you trust a green test run |
Lesson 12, journal |
In Guitar Alchemist’s Directory.Build.props, the PackageReference Update lines meant to align package versions change nothing: the file is imported before the projects’ own items |
Check the version a restore picks; Directory.Build.targets or central package management do what these lines intend. Fix proposed in GA PR #812 |
Lesson 12, QA table |
Prerequisites
Section titled “Prerequisites”- A computer with Windows 10 or 11, a recent Linux distribution (or WSL), or macOS 14 or later.
- About 1 GB of disk for the .NET SDK.
- A terminal: lesson 1 explains how to open one.
- An editor: Visual Studio Code with the C# Dev Kit extension, Visual Studio on Windows, or JetBrains Rider. Lesson 1 compares them.
After this course
Section titled “After this course”An Advanced C# course, written at the same time as this one, starts where it ends: memory, the garbage collector, async under the hood and measured performance. The Java for C# developers and Rust for C#/Java developers courses use C# as their starting point.
Resources
Section titled “Resources”- C# documentation, and its tour of C# and fundamentals.
- C# language reference: every keyword, operator and compiler error.
- .NET CLI overview: the
dotnetcommand. - File-based apps: running a single
.csfile.