// Program.cs -- entire program, no boilerplate needed
Console.WriteLine("Hello, World!");
var numbers = new[] { 1, 2, 3 };
Console.WriteLine(numbers.Sum());
Topics
32
Arrays, Span<T> & Memory<T>
Asynchronous Programming
Attributes & Reflection
Collections
Delegates, Events & Lambdas
Dependency Injection & IoC Principles
Design Patterns in C#
Enums & Flags
Equality: Equals, GetHashCode & IEquatable
Exception Handling
Extension Methods
File I/O & Streams
Fundamentals
Generics
Indexers & Operator Overloading
Interfaces & Abstract Classes
Iterators & yield return
LINQ
Memory & Garbage Collection
Modern C# Features (Global Usings, File-Scoped Namespaces, Top-Level Statements)
Multithreading & Task Parallel Library
Nullable Reference Types
Nullable Value Types (Nullable<T>)
OOP
Records & Pattern Matching
Regular Expressions in C#
Serialization (System.Text.Json)
String Handling & StringBuilder
Structs, Boxing & Unboxing
Tuples & Deconstruction
Unit Testing (xUnit/NUnit/MSTest)
Value vs Reference Types
Modern C# Features (Global Usings, File-Scoped Namespaces, Top-Level Statements)
10 questions found
Top-level statements (C# 9+) let you write executable code directly at the top of a .cs file WITHOUT wrapping it in an explicit Main() method or even a class — the compiler automatically generates the boilerplate Program class and Main method behind the scenes, reducing a minimal console app to just the code that actually matters.
Real-world example
Writing a small utility script or a new minimal ASP.NET Core project's Program.cs without unnecessary ceremony.
Fundamentals
What is a file-scoped namespace declaration, and how does it reduce indentation compared to a traditional block-scoped namespace?
BeginnerA file-scoped namespace (`namespace MyApp.Services;` with a semicolon, no braces) applies to EVERY type declared in the rest of that file, eliminating one level of nested indentation compared to the traditional `namespace MyApp.Services { ... }` block-style syntax — purely a readability/formatting improvement with no behavioral difference.
// Modern: file-scoped namespace, less indentation
namespace MyApp.Services;
public class OrderService { }
// Old: block-scoped namespace, extra indentation level
namespace MyApp.Services {
public class OrderService { }
}
Real-world example
Reducing unnecessary indentation across an entire codebase when every file only ever contains ONE namespace anyway.
Fundamentals
Prefixing a 'using' directive with 'global' (either directly in a .cs file, or conventionally in a dedicated GlobalUsings.cs file) makes that namespace available to EVERY file in the project automatically, without needing to repeat the same common 'using' statements (like System, System.Linq) at the top of every single file.
// GlobalUsings.cs
global using System;
global using System.Linq;
global using System.Collections.Generic;
// Any other file in the project can now use List<T>, LINQ, etc. WITHOUT its own 'using' statements
Real-world example
Eliminating repetitive boilerplate 'using System; using System.Linq;' lines across every file in a large project.
Fundamentals
What does the 'ImplicitUsings' project setting (`<ImplicitUsings>enable</ImplicitUsings>`) do automatically?
IntermediateEnabling ImplicitUsings automatically adds a curated set of GLOBAL using directives for the most commonly-needed namespaces (like System, System.Linq, System.Collections.Generic, and project-type-specific ones like Microsoft.AspNetCore.Builder for web projects) WITHOUT you writing them yourself — the exact set depends on the project's SDK type (console, web, etc.).
<!-- .csproj -->
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<!-- Now System, System.Linq, System.Collections.Generic, etc. are available everywhere automatically -->
Real-world example
Starting a new project with sensible default global usings enabled out of the box, reducing initial boilerplate.
Fundamentals
How do required members (C# 11's 'required' keyword) enforce that certain properties MUST be set during object initialization?
IntermediateMarking a property 'required' forces callers to set it via OBJECT INITIALIZER syntax (or a constructor annotated with [SetsRequiredMembers]) — the compiler raises an error if a required property is left unset when constructing an instance, catching a whole class of 'forgot to set a mandatory field' bugs at compile time instead of leaving a property at its unintended default value.
public class User {
public required string Email { get; set; }
public string? Name { get; set; }
}
var user = new User { Email = "sam@x.com" }; // OK, Email is set
// var bad = new User(); // Error: required member 'Email' must be set
Real-world example
Guaranteeing a DTO or domain object's mandatory fields (like Email or Id) can never be accidentally left unset.
Records & Pattern Matching
How do C# 12's collection expressions (`[1, 2, 3]`) provide a unified, type-agnostic syntax for initializing arrays, lists, and spans?
AdvancedCollection expressions use a single, consistent `[...]` syntax that the compiler adapts to whatever the TARGET TYPE actually is — an array, a List<T>, a Span<T>, or any type implementing the right collection-building pattern — replacing the previously inconsistent mix of 'new[] {...}', 'new List<T> {...}', and other type-specific initialization syntaxes.
int[] array = [1, 2, 3];
List<int> list = [1, 2, 3];
Span<int> span = [1, 2, 3];
int[] combined = [..array, 4, 5, ..list]; // spread operator ('..') combines collections too
Real-world example
Simplifying and unifying collection initialization syntax across arrays, lists, and spans throughout a modern C# codebase.
Arrays
Span<T> & Memory<T>
How do C# 12 primary constructors interact with dependency injection in ASP.NET Core minimal APIs and controller classes?
AdvancedPrimary constructors let a controller (or any DI-managed class) declare its injected dependencies directly in the class header, with those parameters usable throughout the entire class body — eliminating the separate private readonly field declarations and explicit constructor assignment boilerplate previously required for every injected dependency.
// Modern: primary constructor eliminates DI boilerplate
public class OrdersController(IOrderService orderService, ILogger<OrdersController> logger) : ControllerBase {
[HttpGet]
public IActionResult Get() {
logger.LogInformation("Fetching orders");
return Ok(orderService.GetAll());
}
}
// No separate private fields or explicit constructor body needed
Real-world example
Reducing significant boilerplate in ASP.NET Core controllers and services that inject multiple dependencies via the constructor.
Dependency Injection & IoC Principles
How does the 'file' access modifier (C# 11) create a type visible ONLY within its own source file, and what problem does this solve for source generators?
AdvancedThe 'file' modifier restricts a type's visibility to ONLY the file it's declared in — even other classes in the SAME namespace and assembly can't see or reference it — specifically designed to let source generators emit HELPER types with common, simple names (like 'Helpers' or 'Constants') across many generated files WITHOUT any risk of naming collisions between them.
// GeneratedFile1.g.cs
file class Helpers { public static string Format(string s) => s.Trim(); } // invisible outside this file
// GeneratedFile2.g.cs
file class Helpers { public static int Format(int n) => n; } // a DIFFERENT, non-conflicting 'Helpers' type
Real-world example
Understanding why source-generator-emitted code can safely reuse simple, common type names across many generated files without collisions.
Attributes & Reflection
How do C# 12's default parameter values on LAMBDA expressions work, and what limitation did they remove compared to earlier C# versions?
AdvancedPrior to C# 12, lambda expressions couldn't declare DEFAULT parameter values the way regular methods and local functions could; C# 12 removes that restriction, letting a lambda assigned to a delegate type declare defaults directly, matching regular method flexibility.
var greet = (string name, string greeting = "Hello") => $"{greeting}, {name}!";
Console.WriteLine(greet("Sam")); // "Hello, Sam!" -- uses the default
Console.WriteLine(greet("Sam", "Hi")); // "Hi, Sam!"
Real-world example
Simplifying a small inline lambda-based utility that previously required a full local function just to support an optional parameter.
Delegates
Events & Lambdas
How do C# 11's raw string literals (`"""..."""`) simplify writing strings containing quotes, escape sequences, or multi-line content like JSON or SQL?
AdvancedRaw string literals (delimited by three or more double-quotes) let you write ANY content — including literal double quotes, backslashes, and multi-line text — WITHOUT any escaping at all, and support string interpolation via an adjusted number of leading '$' characters when needed, making embedded JSON, SQL, or regex patterns dramatically more readable.
string json = """
{
"name": "Sam",
"path": "C:\\Users\\Sam"
}
"""; // no escaping needed for quotes or backslashes at all
string interpolated = $"""
Hello, {name}! Your path is "C:\literal\path".
""";
Real-world example
Embedding a readable, unescaped JSON payload, SQL query, or regex pattern directly as a C# string literal without escape-character clutter.
String Handling & StringBuilder