C# & .NET Platform Architecture
A modern, type-safe, object-oriented language paired with a high-performance cross-platform runtime engine. Built for enterprise software, web microservices, game engines, and cloud-native computing.
History & Origin of C# and .NET
C# was unveiled in 2000 by Microsoft, designed under the leadership of Anders Hejlsberg (creator of Turbo Pascal and principal architect of Delphi). Designed as a key language for the new .NET Framework, C# aimed to combine the high productivity of Visual Basic with the raw structural power of C++.
C# & .NET Major Version Timeline
Milestones of C# Evolution
Introduced managed code on Windows, followed by compile-time type safety via Generics, anonymous methods, and nullable value types.
Brought functional features: LINQ, Lambda expressions, extension methods, and anonymous types.
Transformed concurrent programming by introducing native compiler-generated async / await state machines.
Transitioned to open-source, cross-platform architecture (Linux, macOS, Windows) with Records, Pattern Matching, Minimal APIs, and Native AOT compilation.
Installation & .NET SDK Setup
To develop C# applications, install the official cross-platform .NET SDK (Software Development Kit). The SDK includes the Roslyn C# compiler, the CLR runtime execution engine, and the dotnet Command-Line Interface (CLI).
Full-featured IDE for Windows with integrated debugging, profiler, and enterprise tools.
Lightweight cross-platform editor with IntelliSense, Solution Explorer, and unit test runner.
Cross-platform .NET IDE offering deep code refactoring and performance profiling.
# 1. Verify installed .NET SDK version
dotnet --info
# 2. Create a new Console Application
dotnet new console -o UndrstandingApp
# 3. Change directory and run the application
cd UndrstandingApp
dotnet run
Anatomy of a C# Program: using, namespace, and class
Every C# application is constructed from fundamental building blocks: using directives to import standard libraries, namespace declarations to logically group types, and class blueprints containing methods, fields, and constructors.
Imports existing namespaces (e.g. using System;) so you can use types like Console or List<T> without writing full qualifiers like System.Console.
Provides a logical container for your classes, preventing class name collisions across large projects and external packages.
File-Scoped Syntax:namespace UndrstandingApp; (omits extra indentation braces).
The fundamental Object-Oriented building block encapsulating state (fields/properties) and behavior (methods) with access modifiers like public or private.
public class Program { ... }
The mandatory runtime entry point invoked by the CLR when the executable starts up. static allows execution without instantiating the class first.
static void Main(string[] args)
Modern Top-Level Syntax (C# 9+)
// Program.cs (Top-Level Statements)
// Roslyn auto-wraps namespace & Main()
using System;
Console.WriteLine("Hello, Undrstanding!");
GreetUser("Developer");
// Local function declaration
void GreetUser(string name)
{
Console.WriteLine($"Welcome, {name}!");
}
Traditional Program Structure
using System; // 1. Import
namespace UndrstandingApp; // 2. Scope
public class Program // 3. Class
{
public static void Main(string[] args) // 4. Entry
{
Console.WriteLine("Hello, World!");
GreetUser("Developer");
}
static void GreetUser(string name) =>
Console.WriteLine($"Welcome, {name}!");
}
Variable Declarations, Data Types & Constants
C# is a strongly-typed language. You can declare variables explicitly with data types or implicitly using the var keyword (where the compiler infers the exact type at compile time).
Value Types (Stack) vs Reference Types (Managed Heap)
// Explicit Variable Declarations
int age = 25;
double score = 98.5;
decimal price = 19.99m; // High precision decimal for financial data
bool isActive = true;
string platformName = "Undrstanding";
// Implicit Typing with 'var' (Type inferred as string at compile time)
var userEmail = "student@undrstanding.com";
// Compile-Time Constant vs Readonly Field
const double Pi = 3.14159265;
readonly DateTime ServerStartTime = DateTime.UtcNow;
Console.WriteLine($"User: {userEmail} | Score: {score}");
Console.WriteLine($"Price: ${price} | Active: {isActive}");
Conditionals, Switch Expressions & Iteration Loops
C# supports standard conditional branching (if, else if, else), pattern-matching switch expressions, and iteration loops (foreach, for, while, do-while).
// 1. Iteration with 'foreach' over array
string[] topics = { "CLR", "LINQ", "Async", "Span" };
foreach (var topic in topics)
{
Console.WriteLine($"Studying: {topic}");
}
// 2. Pattern Matching Switch Expression
int statusCode = 200;
string message = statusCode switch
{
200 => "Success / OK",
404 => "Resource Not Found",
500 => "Internal Server Error",
_ => "Unknown HTTP Status"
};
Console.WriteLine($"Status {statusCode}: {message}");
The Common Language Runtime (CLR) & Execution Engine
C# source code compiles into Common Intermediate Language (CIL/MSIL) bytecode rather than raw machine instructions. At execution time, the CLR's Just-In-Time (JIT) compiler translates bytecode into optimized native CPU instructions while managing type safety and automatic memory reclamation.
CLR Garbage Collector Generations Architecture
// C# Compilation & Execution Pipeline
C# Source (.cs) ➔ Roslyn Compiler ➔ CIL Bytecode (.dll) ➔ CLR JIT ➔ Native Machine Code
Value Types, Reference Types & Boxing
C# segregates memory allocation into Value Types (primitives, structs on the stack) and Reference Types (classes, arrays, delegates on the managed heap). Boxing converts a value type to an object reference, incurring a heap allocation performance penalty.
// 1. Immutable Record Declaration (C# 9+)
public record UserProfile(string Id, string Email, DateTime CreatedAt);
// 2. Pattern Matching with Switch Expressions
public static decimal CalculateDiscount(object customer) => customer switch
{
UserProfile { CreatedAt: var date } when date.Year < 2020 => 0.20m,
UserProfile _ => 0.05m,
null => 0.0m,
_ => throw new ArgumentException("Unknown customer type")
};
// 3. Nullable Reference Types & Coalescing Operator
string? input = null;
string displayName = input?.Trim() ?? "Anonymous Student";
Console.WriteLine($"Display Name: {displayName}");
Span<T>, Memory<T> & Zero-Allocation Slicing
Span<T> is a stack-only ref struct representing a contiguous region of arbitrary memory (managed heap arrays, stack memory via stackalloc, or native unmanaged pointers) without allocation overhead.
Span<char> Contiguous Memory Slice (Zero Heap Allocation)
// Zero-Allocation String Slicing with ReadOnlySpan<char>
string rawHeader = "Authorization: Bearer eyJhbGciOiJIUzI1Ni...";
ReadOnlySpan<char> span = rawHeader.AsSpan();
// Slice without allocating a new string object
ReadOnlySpan<char> token = span.Slice(15, 6);
Console.WriteLine($"Sliced Token: {token.ToString()}");
Console.WriteLine($"Span Length: {token.Length} chars");
Generics, Variance & Events
C# provides compile-time type safety with Generics and supports Generic Variance: Covariance (out T) for output types and Contravariance (in T) for input parameter types.
// Generic Repository Interface with Type Constraints & Covariance
public interface IReadOnlyRepository<out TEntity, in TId>
where TEntity : class
where TId : notnull
{
Task<TEntity?> GetByIdAsync(TId id, CancellationToken ct = default);
}
// Strongly-Typed Event Handler Delegate
public class DataEngine
{
public event Action<string>? OnProcessed;
public void Execute()
{
OnProcessed?.Invoke("Data pipeline processing finished successfully.");
}
}
var engine = new DataEngine();
engine.OnProcessed += msg => Console.WriteLine($"[EVENT] {msg}");
engine.Execute();
LINQ Architecture: IEnumerable vs IQueryable
LINQ standardizes querying over collections. IEnumerable<T> operates on in-memory collections using delegates, whereas IQueryable<T> compiles queries into Expression Trees for remote SQL database translation.
var numbers = new List<int> { 1, 2, 3, 4, 5 };
// Query defined (Deferred Execution - Not processed yet)
var query = numbers
.Where(n => n % 2 == 0)
.Select(n => n * 10);
numbers.Add(6); // Mutate list after query definition
// Execution triggered HERE during enumeration
foreach (var item in query)
{
Console.WriteLine(item);
}
Async State Machines & Thread Pool Context
The Roslyn compiler transforms async methods into state machine structs behind the scenes. Using ConfigureAwait(false) suppresses capturing the current SynchronizationContext, yielding superior throughput in server applications.
public async Task<string> DownloadPayloadAsync(string url, CancellationToken ct)
{
using var client = new HttpClient();
// Non-blocking asynchronous network request avoiding context capture
Console.WriteLine($"[ASYNC] Dispatching request to {url}...");
var response = await client.GetAsync(url, ct).ConfigureAwait(false);
return await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
}
ASP.NET Core & Dependency Injection Lifetimes
Unified .NET provides built-in IoC Dependency Injection with three primary service lifetimes:
Created every time requested from container.
Created once per HTTP Request connection scope.
Single instance shared across entire app lifetime.
C# & .NET Glossary
Execution engine for .NET applications providing GC, type safety, and JIT compilation.
Common Intermediate Language bytecode emitted by C# Roslyn compiler.
Stack-allocated ref struct providing contiguous zero-allocation memory slicing.
Language Integrated Query for operating on data sources in functional syntax.
Heap partition for objects larger than 85,000 bytes, avoiding frequent GC compaction copies.
Ahead-Of-Time compilation directly generating standalone native binary executables without JIT.
Knowledge Check (10 Assessment Questions)
Verify your understanding of C# syntax, SDK installation, CLR runtime mechanics, Span memory slicing, LINQ, and ASP.NET Core architecture. Pass all 10 questions to earn your certificate.