From "what is Console.WriteLine" to "I architect zero-allocation cloud backends and FinTech trading engines." Modern C# explained like you're human.
// In modern C#, no boilerplate class Program or static void Main needed! // This entire Program.cs is just 4 lines: Console.WriteLine("Welcome to Modern C# & .NET!"); string user = "Kv"; int level = 99; // String interpolation with $ is clean, readable, and type-safe Console.WriteLine($"Pilot: {user}, Flight Level: {level:D3}"); // Raw String Literals (C# 11+): Triple quotes allow multi-line strings & unescaped quotes! string json = """ { "status": "nominal", "velocity": 28000 } """;
dotnet new console -n MyApp then dotnet run. That's literally the whole setup.| Category | Types | Where stored / Behavior |
|---|---|---|
| Value Types | int, double, bool, char, decimal, struct, enum | Stored directly on the Stack (or inlined). Copied by value. Cannot be null unless marked T?. |
| Reference Types | string, object, class, record, interface, delegate, array | Object data lives on the Heap. Variable holds a reference (pointer). Managed by Garbage Collector. |
int a = 10; int b = a; // b gets a copy of 10. Modifying b does NOT touch a! int[] arr1 = [1, 2, 3]; // C# 12 collection expression int[] arr2 = arr1; // arr2 points to the SAME array in heap! arr2[0] = 999; // arr1[0] is now 999!
// Non-nullable string: compiler yells if you assign null! string definitelyText = "Falcon 9"; // Nullable string (string?): can be null explicitly string? maybeText = null; // 1. Null-conditional operator (?.) int? length = maybeText?.Length; // null, no NullReferenceException! // 2. Null-coalescing operator (??) provides fallback string name = maybeText ?? "Unknown Pilot"; // 3. Null-coalescing assignment (??=) maybeText ??= "Default Value"; // assigns only if currently null // 4. Null-forgiving operator (!) tells compiler "trust me, it's not null" int len = maybeText!.Length;
NullReferenceException bugs at compile-time!// Modern switch expression: clean, functional syntax with return values int altitude = 85000; string layer = altitude switch { < 12000 => "Troposphere", >= 12000 and < 50000 => "Stratosphere", >= 50000 and < 85000 => "Mesosphere", >= 85000 => "Thermosphere / Space", _ => "Unknown" // default fallback }; // Property pattern matching on objects public record RocketState(bool IsStaged, double FuelPercent); string GetStatus(RocketState state) => state switch { { FuelPercent: <= 0 } => "Main Engine Cutoff (MECO)", { IsStaged: true } => "Stage 2 Burn Active", _ => "Stage 1 Boost" };
// Target-typed new() avoids repeating long type names Dictionary<string, List<int>> telemetry = new(); // C# 12 Collection Expressions: unified syntax for arrays, lists, spans! int[] numbers = [1, 2, 3, 4, 5]; List<string> crew = ["Neil", "Buzz", "Michael"]; // Spread operator (..) flattens arrays inside collection expressions int[] extra = [6, 7]; int[] combined = [..numbers, ..extra, 8, 9]; // [1, 2, 3, 4, 5, 6, 7, 8, 9]
try { File.ReadAllText("flight_plan.json"); } catch (FileNotFoundException ex) { Console.WriteLine($"Missing config: {ex.FileName}"); } // Exception filters with 'when': only catches if condition is true! catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.GatewayTimeout) { Console.WriteLine("Satellite link timed out. Retrying..."); } finally { // ALWAYS runs whether an exception occurred or not Console.WriteLine("Cleanup finished."); }
// C# 12 Primary Constructor directly on the class declaration! public class SpaceProbe(string name, double distanceAu) { // name and distanceAu are in scope across the entire class! public string Callsign { get; } = name; public double Distance { get; set; } = distanceAu; // Expression-bodied method public void PingEarth() => Console.WriteLine($"[{name}] Telemetry ping from {Distance} AU"); } var voyager = new SpaceProbe("Voyager 1", 163.5); voyager.PingEarth();
// 'record' provides built-in value-based equality, ToString, & deconstruction! public record TelemetryPacket(Guid Id, string Sensor, double Value); var p1 = new TelemetryPacket(Guid.NewGuid(), "Pressure", 101.3); var p2 = new TelemetryPacket(p1.Id, "Pressure", 101.3); // 1. Value equality: true because all properties match! (classes would be false) Console.WriteLine(p1 == p2); // True! // 2. Non-destructive mutation with 'with' expression var p3 = p1 with { Value = 104.8 }; // creates clone with modified Value! // 3. Deconstruction var (id, sensor, val) = p3;
record class or record struct for DTOs, API models, events, and message queues!// 1. readonly struct: Guarantees immutability. Lets CLR skip defensive copying! public readonly struct Vector3D { public double X { get; } public double Y { get; } public double Z { get; } public Vector3D(double x, double y, double z) => (X, Y, Z) = (x, y, z); } // 2. ref struct (STACK ONLY): CANNOT be boxed, cannot be stored in heap class. // Zero garbage collector overhead! (Used for Span) public ref struct StackOnlyBuffer { public Span<byte> Memory; }
public class LaunchConfig { // 'init' allows setting value ONLY during object initialization (immutable after!) public string MissionCode { get; init; } = "ARTEMIS-II"; // Auto-property with default initializer public int RetryCount { get; set; } = 3; // Required modifier (C# 11): caller MUST supply this during new { ... } public required string TargetOrbit { get; init; } } var config = new LaunchConfig { TargetOrbit = "Lunar Transfer", RetryCount = 5 }; // config.TargetOrbit = "LEO"; // ERROR: init-only property!
public interface IEngine { void Ignite(); double ThrustKn { get; } // Default Interface Implementation: can provide fallback logic! void EmergencyShutdown() { Console.WriteLine("EMERGENCY: Cutting fuel valves immediately!"); } } public class IonThruster : IEngine { public double ThrustKn => 0.25; public void Ignite() => Console.WriteLine("Xenon plasma activated."); // Inherits default EmergencyShutdown() without needing to re-implement it }
public abstract class Satellite { public abstract void BroadcastTelemetry(); public virtual void CalibrateSensors() => Console.WriteLine("Default calibration"); } public class GpsSatellite : Satellite { public override void BroadcastTelemetry() => Console.WriteLine("Atomic clock: 10:00:00.000"); // 'sealed override' prevents any derived class from overriding this method again public sealed override void CalibrateSensors() => Console.WriteLine("Atomic clock locked."); } // 'sealed' on class prevents any other class from inheriting from it public sealed class SecureTransponder {}
// 1. List— Dynamic resizing array List<int> scores = [85, 92, 78]; scores.Add(99); scores.RemoveAt(0); // 2. Dictionary— Fast O(1) Hash Map Dictionary<string, int> frequencies = new() { ["S-Band"] = 2200, ["X-Band"] = 8400 }; if (frequencies.TryGetValue("X-Band", out int mhz)) { Console.WriteLine($"Freq: {mhz} MHz"); } // 3. HashSet— O(1) Unique element set HashSet<string> activeNodes = ["NodeA", "NodeB"]; bool added = activeNodes.Add("NodeA"); // false, already exists
public record Planet(string Name, double MassEarths, bool HasRings); List<Planet> solarSystem = [ new("Mercury", 0.055, false), new("Earth", 1.0, false), new("Saturn", 95.2, true), new("Jupiter", 317.8, true) ]; // Fluent LINQ Pipeline (Lazily evaluated!) var giantRingPlanets = solarSystem .Where(p => p.HasRings && p.MassEarths > 10.0) .OrderByDescending(p => p.MassEarths) .Select(p => $"Planet: {p.Name} ({p.MassEarths}x Earth)") .ToList(); // executes query here // Aggregate helpers double totalMass = solarSystem.Sum(p => p.MassEarths); bool hasGiant = solarSystem.Any(p => p.MassEarths > 300); // true
// yield return generates elements ONE AT A TIME on demand! // Never allocates a giant 1,000,000 element array in RAM! public static IEnumerable<int> GeneratePrimes(int max) { for (int i = 2; i <= max; i++) { if (IsPrime(i)) { yield return i; // pauses execution & yields value to caller! } } } // Consumes elements without preloading everything foreach (var prime in GeneratePrimes(100).Take(5)) { Console.WriteLine(prime); // 2, 3, 5, 7, 11 }
// Standard string.Substring() ALWAYS allocates a NEW string on the heap. // ReadOnlySpanslices memory directly with ZERO GC allocations! string telemetryHeader = "MISSION-APOLLO-19690720-PASS"; // AsSpan() creates a window over existing string in memory ReadOnlySpan<char> span = telemetryHeader.AsSpan(); ReadOnlySpan<char> mission = span.Slice(8, 6); // "APOLLO" (0 bytes allocated!) ReadOnlySpan<char> date = span.Slice(15, 8); // "19690720" // Fast parsing without allocating strings int year = int.Parse(date.Slice(0, 4)); // 1969
Span<T> to parse millions of HTTP requests per second with near-zero garbage collection pauses!// 1. Action: Delegate pointing to a function returning VOID Action<string> log = (msg) => Console.WriteLine($"[LOG] {msg}"); log("Engines started"); // 2. Func: Delegate returning a VALUE (last generic param is return type) Func<double, double, double> calcKineticEnergy = (mass, velocity) => 0.5 * mass * velocity * velocity; double joules = calcKineticEnergy(5000, 7800); // orbital speed energy // 3. Predicate: Returns bool (equivalent to Func Predicate<int> isSafeTemp = t => t > -50 && t < 120;)
using System.Net.Http.Json; public async Task<TelemetryReport> FetchTelemetryAsync(string satelliteUrl) { using var http = new HttpClient(); // Await yields the thread back to the thread pool while waiting for network I/O! // Zero threads blocked during download. var data = await http.GetFromJsonAsync<TelemetryReport>(satelliteUrl); return data ?? throw new InvalidOperationException("No data received"); } // ValueTask: Avoids heap allocating a Task object when result is already cached! public ValueTask<int> GetCachedPingAsync() { if (_isCached) return new ValueTask<int>(_cachedPing); return new ValueTask<int>(FetchPingFromNetworkAsync()); }
// 1. CancellationTokenSource enables graceful timeout / abort using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); try { await Task.Delay(10000, cts.Token); } catch (OperationCanceledException) { Console.WriteLine("Operation aborted within 5s deadline!"); } // 2. Running multiple async operations in parallel Task<string> t1 = GetSensorAAsync(); Task<string> t2 = GetSensorBAsync(); // Waits for ALL tasks to finish concurrently string[] results = await Task.WhenAll(t1, t2);
// Streams data asynchronously as it arrives over network/websocket public static async IAsyncEnumerable<double> StreamSensorReadingsAsync() { for (int i = 0; i < 10; i++) { await Task.Delay(100); // simulate live telemetry arrival yield return Random.Shared.NextDouble() * 100.0; } } // Consume with 'await foreach' await foreach (var val in StreamSensorReadingsAsync()) { Console.WriteLine($"Live reading: {val:F2}"); }
| Generation | Purpose | Collection Speed |
|---|---|---|
| Gen 0 | Brand new short-lived objects (buffers, temp strings). | Sub-millisecond (ultra fast) |
| Gen 1 | Buffer zone between short-lived and long-lived. | Very fast |
| Gen 2 | Long-lived objects (caches, singletons, app state). | Full GC (costlier) |
| LOH | Large Object Heap (>= 85,000 bytes). Avoid frequent allocs! | Collected with Gen 2 |
// IDisposable pattern with modern 'using var' statement public class HardwarePort : IDisposable { public void Dispose() { // Free unmanaged handles / socket / file descriptors GC.SuppressFinalize(this); } } void Execute() { using var port = new HardwarePort(); // Disposed AUTOMATICALLY when Execute() exits! }
// 1. stackalloc allocates bytes directly on the STACK (zero GC pressure!) Span<byte> buffer = stackalloc byte[256]; buffer[0] = 0xFF; // 2. Raw C-style pointers with unsafe keyword unsafe { int val = 42; int* p = &val; *p = 100; // directly writes to memory address // 'fixed' pins a managed heap object so GC won't move it during pointer access byte[] arr = [10, 20, 30]; fixed (byte* pArr = arr) { *(pArr + 1) = 99; // arr[1] is now 99 } }
// Multiple constraints define exact type requirements public class TelemetryRepository<T> where T : class, IComparable<T>, new() { public T CreateAndValidate() { T item = new T(); // legal because of new() constraint return item; } } // 'unmanaged' constraint: types that contain NO reference types (can be memcopied!) public static void ZeroMemory<T>(ref T val) where T : unmanaged { unsafe { fixed (T* ptr = &val) { Unsafe.InitBlock(ptr, 0, (uint)sizeof(T)); } } }
// Modern C# replaces slow runtime reflection with COMPILE-TIME Source Generators! public record FlightPlan(string Mission, int TargetAltitudeKm); // Compile-time JSON Serializer Context (Zero reflection, blazing fast, Native AOT safe!) [JsonSerializable(typeof(FlightPlan))] public partial class AppJsonContext : JsonSerializerContext {} // Usage with source-generated serializer var plan = new FlightPlan("Europa Clipper", 628300000); string json = JsonSerializer.Serialize(plan, AppJsonContext.Default.FlightPlan);
| Lifetime | Method | When to use |
|---|---|---|
| Transient | AddTransient<I, T>() | New instance created every time requested (lightweight stateless services). |
| Scoped | AddScoped<I, T>() | One instance per HTTP Request / processing unit (DbContext, unit of work). |
| Singleton | AddSingleton<I, T>() | Single instance shared for entire app lifetime (in-memory caches, channels). |
var builder = WebApplication.CreateBuilder(); builder.Services.AddSingleton<ITelemetryChannel, TelemetryChannel>(); var app = builder.Build(); // Minimal API endpoint with injected service app.MapGet("/health", (ITelemetryChannel ch) => ch.GetStatus()); app.Run();
using System.Threading.Channels; // Bounded channel prevents producer from overwhelming RAM (Backpressure!) var channel = Channel.CreateBounded<TelemetryPacket>(new BoundedChannelOptions(50000) { FullMode = BoundedChannelFullMode.Wait, SingleReader = true, SingleWriter = false }); // Producer: Writes packets asynchronously await channel.Writer.WriteAsync(new TelemetryPacket(Guid.NewGuid(), "Gyro", 0.05)); // Consumer: Reads stream with zero locks await foreach (var packet in channel.Reader.ReadAllAsync()) { ProcessPacket(packet); }
using System.Threading; public class HighFrequencyMetrics { private long _processedOrders = 0; private double _maxLatencyMs = 0.0; public void RecordOrder() { // Atomic hardware increment — 100x faster than lock(_syncObj)! Interlocked.Increment(ref _processedOrders); } // Compare-And-Swap (CAS) pattern in C# public void UpdateMaxLatency(double latency) { double current; do { current = _maxLatencyMs; if (latency <= current) return; } while (Interlocked.CompareExchange(ref _maxLatencyMs, latency, current) != current); } }
using System.Buffers; // 1. ArrayPool rents buffers from shared bucket and returns them (0 heap allocations!) byte[] rentedArray = ArrayPool<byte>.Shared.Rent(4096); try { ProcessBuffer(rentedArray); } finally { ArrayPool<byte>.Shared.Return(rentedArray); } // 2. UTF-8 String Literals (u8): Compiled directly as ReadOnlySpanwithout encoding! ReadOnlySpan<byte> authHeader = "Authorization: Bearer Token"u8; ReadOnlySpan<byte> okStatus = "HTTP/1.1 200 OK\r\n"u8;
| Command | What it does |
|---|---|
dotnet new console | Create new console application project |
dotnet new webapi -minimal | Create high-performance Minimal Web API project |
dotnet run | Build and execute the current project |
dotnet watch | Hot-reloads app upon any file save (blazing fast dev cycle) |
dotnet add package Name | Install a NuGet package dependency |
dotnet publish -c Release -r win-x64 --self-contained | Create standalone single-file binary with zero runtime prerequisites |
dotnet test | Run xUnit / NUnit unit tests |
| Namespace | What it provides |
|---|---|
System | Object, String, Console, Math, Exception, Guid, DateTime |
System.Collections.Generic | List<T>, Dictionary<K,V>, HashSet<T>, Queue<T> |
System.Linq | Enumerable extension methods (Where, Select, OrderBy) |
System.Threading.Tasks | Task, Task<T>, ValueTask, Parallel |
System.Threading.Channels | Lock-free high-throughput pub-sub queues |
System.Text.Json | High-performance UTF8 JSON serializer & AOT generators |
System.Buffers | ArrayPool<T>, MemoryPool<T>, ReadOnlySequence<T> |
System.IO | File, Directory, Path, Stream, FileStream |