Last Updated: May 17, 2026
C# powers everything from web APIs and desktop apps to game engines and mobile clients because of a specific mix of language and runtime features. This chapter is a guided tour, not a deep dive. We'll walk through each headline feature, show a tiny snippet of it in action, and explain why it matters. Several of these get full sections of their own later in the course, so we'll keep things light here and save the long explanations for when you have more context.
Some of these features live in the language itself, things like properties, pattern matching, and nullable annotations. Some live in the runtime, like garbage collection and the JIT compiler. A few are really about the standard library: LINQ, async helpers, the deep collection types. Taken together, they're what people mean when they say "C#".
The type system is where C# spends a lot of its budget. Most of what feels productive about the language traces back to how seriously it treats types.
Every variable, parameter, and return value has a type that the compiler knows about. If you try to assign a number to a variable that holds text, the build fails and you find out at your desk instead of at 2 a.m. in production.
You don't ship that bug. The compiler is doing real work for you here, and it does it before the program ever runs. Whole sections of this course (Basic Syntax, and Structs & Enums) explore the type system in detail.
C# was object-oriented from day one. You model real things as classes that hold data and expose behavior. A Product knows its name and price. A Cart knows the products it holds. An Order knows its status.
That class keyword, the four classical OOP ideas (encapsulation, inheritance, polymorphism, abstraction), and a modern alternative called records are all first-class. The OOP sections cover them end to end, and the Modern C# Features section covers records in depth. For now, the point is that organizing code around objects is the default in C#, not a bolt-on.
Properties look like fields when you use them, but they're actually method pairs the compiler generates for you. They give you a clean way to expose data while keeping room to add validation or logic later without breaking callers.
The { get; set; } syntax is a property. Most C# developers reach for properties by default and almost never expose raw public fields. The Object-Oriented Programming section has a full lesson on properties.
In modern C#, the compiler tracks whether a reference can be null. If you declare a parameter as string, the compiler assumes it isn't null and warns you when you treat it like it might be. If you want it to be nullable, you write string?.
This catches a huge class of NullReferenceException bugs before they ship.
The runtime handles the parts of programming that are easy to get wrong, and the language ships with productivity features that would be separate libraries elsewhere.
You allocate objects with new, and the runtime reclaims them when no part of your program can reach them anymore. There's no free(), no delete, no manual cleanup of memory. The garbage collector tracks reachability and frees what's no longer in use.
That removes whole categories of bugs: use-after-free, double-free, leaked allocations. The Memory Management section is dedicated to this, including how the GC actually works.
Generics let you write code once and use it with any type. The classic example is List<T>. There's no separate ListOfProduct or ListOfOrder. There's one definition, and you tell it what type it holds.
The compiler enforces that you can only put Product objects into inventory. Try to add a string and the build fails. You get reusable containers without losing type safety. The Generics section covers them in depth, including constraints, variance, and generic methods.
LINQ stands for Language Integrated Query. It gives you one consistent way to filter, transform, group, and aggregate data, whether that data lives in a list, an array, an XML document, or a database. The same query syntax works on all of them.
Where filters. Sum aggregates. The lambda p => p.Price > 5m is the condition. LINQ feels like SQL inside your C# code, which is exactly what it was designed for. The LINQ section is dedicated to it.
async and await let you write asynchronous code that reads like sequential code. Instead of registering callbacks or chaining .Then() calls, you just await an operation and pick up where it left off when it finishes.
The await keyword tells the runtime "pause this method, free the thread, and resume when the result is ready". The thread isn't blocked while you wait. For a web server that handles thousands of requests at once, this is the difference between scaling and falling over. The Async Programming section covers async in depth.
Pattern matching replaces long chains of if/else with concise, readable expressions. The switch expression is the most common form.
You match on values, types, properties, and shapes. The compiler also warns you when you haven't covered every possible case. The Pattern Matching section covers this in detail, including property patterns, list patterns, and relational patterns.
C# isn't just a language. It rides on a platform (.NET) that does most of the heavy lifting, and that platform is what makes the same C# code run almost anywhere.
A C# program built today runs natively on Windows, Linux, and macOS. The same source compiles to the same intermediate format, and a runtime called the CLR executes it on each platform. For mobile, MAUI (Multi-platform App UI) extends this to iOS and Android with a single shared codebase.
That portability is a big reason teams pick .NET for backend services that have to deploy to mixed environments. The _.NET Ecosystem (CLR, BCL, SDK)_ lesson digs into this, so we won't go deeper here.
The BCL (Base Class Library) is the standard library that ships with .NET. It's deep. You get collections, file I/O, networking, JSON serialization, threading, regular expressions, cryptography, date and time handling, and a lot more, all without installing anything extra.
That JsonSerializer came from the BCL. No NuGet package, no third-party library. For most everyday work (the Collections, File I/O, and Networking sections cover these respectively), the BCL is enough on its own.
C# is usually fast enough by default, but the language and runtime give you escape hatches when you need to push harder.
For most code, the garbage collector and JIT compiler hit a good balance of safety and speed. When you need more, C# has features that look surprisingly low-level.
`Span<T>` lets you work with slices of memory without allocating new arrays. Read a chunk of a large string, do work on it, and never copy. `ref struct` lets you build types that the runtime guarantees stay on the stack, which keeps allocations off the GC's plate entirely. P/Invoke lets you call into native C libraries directly when you need to talk to the operating system or use a library that doesn't have a .NET wrapper.
Slice doesn't copy. It returns a view into the same memory. The Memory Management section covers Span<T> and friends in depth.
On top of that, .NET supports AOT (Ahead-of-Time) compilation, where the runtime compiles your code to native instructions ahead of time instead of relying on the JIT at startup. That's useful for serverless functions, command-line tools, and other places where startup time matters. The Best Practices section touches on this under performance.
| Feature | What It Means |
|---|---|
| Strong Static Typing | Compiler checks types at build time |
| Object-Oriented | Code organized around classes and objects |
| Garbage Collection | Automatic memory management, no manual delete |
| Properties | { get; set; } syntax exposes data with validation hooks |
| Nullable Reference Types | string? vs string catches null bugs at compile time |
| Generics | Write code once, use it with any type |
| LINQ | One consistent way to query collections |
| Async / Await | Asynchronous code that reads sequentially |
| Pattern Matching | Concise conditional logic with switch expressions |
| Cross-Platform | Same code runs on Windows, Linux, macOS, mobile via MAUI |
| Rich BCL | Standard library covers collections, I/O, JSON, threading, networking |
| Interop & Performance | Span<T>, ref struct, P/Invoke, AOT compilation |
new and never call free or delete.NullReferenceException bugs from runtime to compile time.Span<T>, ref struct, P/Invoke, and AOT give you a path down to high-performance and native interop when you need it.Now that we've seen what C# offers, the _.NET Ecosystem (CLR, BCL, SDK)_ lesson digs into the platform that powers all of it.