C# & .NET Framework The .NET Grand Finale
💡
Exercise 48

.NET Runtime Internals — The City's Maintenance Department 20 XP Hard

Ctrl+Enter Run Ctrl+S Save

🏛️ .NET Runtime Internals

Every great city has an invisible infrastructure — water treatment plants, power grids, garbage collection trucks. The .NET runtime is your city's maintenance department: it compiles code on the fly (JIT), manages memory (GC), loads assemblies, and keeps everything humming.

⚙️ The Common Language Runtime (CLR)

The CLR is the execution engine for .NET. When you compile C# code, it becomes Intermediate Language (IL), not native machine code. At runtime, the CLR's Just-In-Time (JIT) compiler converts IL into native instructions for your specific CPU.

  • First call — JIT compiles the method (Tier 0: quick, unoptimized).
  • Hot methods — After enough calls, the runtime recompiles with Tier 1 optimizations (inlining, dead code elimination).
  • ReadyToRun (R2R) — Pre-compiled native images shipped with the app for faster startup.

🗑️ Garbage Collection (GC)

The GC is the city's fleet of garbage trucks. It automatically reclaims memory from objects that are no longer reachable. .NET uses a generational collector:

  • Generation 0 — Short-lived objects (local variables, temporary strings). Collected most frequently.
  • Generation 1 — Objects that survived one Gen 0 collection. Acts as a buffer between short-lived and long-lived.
  • Generation 2 — Long-lived objects (static data, caches). Collected least often — a full GC is expensive.
  • Large Object Heap (LOH) — Objects ≥ 85,000 bytes go here. Collected with Gen 2 but not compacted by default.
// Force a garbage collection (don't do this in production!) GC.Collect(0); // Collect Generation 0 Console.WriteLine("GC Generation 0 collected"); // Check which generation an object is in var obj = new object(); int gen = GC.GetGeneration(obj); Console.WriteLine($"Object is in Gen {gen}");

🔍 Assemblies & Reflection

An assembly is a compiled unit (.dll or .exe) containing IL code, metadata, and resources. Reflection lets you inspect types, methods, and properties at runtime.

using System.Reflection; // Get the current assembly Assembly asm = Assembly.GetExecutingAssembly(); Console.WriteLine($"Assembly: {asm.GetName().Name}"); // Inspect a type Type t = typeof(string); Console.WriteLine($"Type: {t.FullName}"); Console.WriteLine($"Methods: {t.GetMethods().Length}");

♻️ IDisposable & the using Statement

Some resources (files, database connections, network sockets) aren't managed by the GC — you must release them manually. IDisposable provides a Dispose() method, and the using statement ensures it's called even if an exception occurs.

class CityResource : IDisposable { public CityResource() => Console.WriteLine("Resource acquired"); public void Dispose() => Console.WriteLine("Disposed: Resource freed"); } // using statement guarantees Dispose is called using (var res = new CityResource()) { // Use the resource } // Dispose() called automatically here

📦 Value Types vs Reference Types

  • Value types (int, double, struct, enum) — stored on the stack (when local). Copied on assignment. No GC overhead.
  • Reference types (class, string, array, delegate) — stored on the heap. Variables hold a reference (pointer). Subject to GC.
  • Boxing — wrapping a value type in an object (heap allocation). Avoid in hot paths.
  • Weak referencesWeakReference<T> allows GC to collect the object if no strong references remain. Useful for caches.
📋 Instructions
**The City Maintenance Department** Write a program that demonstrates runtime internals: 1. Call `GC.Collect(0)` and print `"GC Generation 0 collected"` 2. Use `Assembly.GetExecutingAssembly().GetName().Name` and print `"Assembly: {name}"` 3. Use `typeof(string).FullName` and print `"Type: {fullName}"` 4. Create a `CityResource` class implementing `IDisposable`: - `Dispose()` prints `"Disposed: Resource freed"` 5. Use a `using` block to create and dispose the resource 6. Print `"Runtime: .NET is powerful!"`
Call GC.Collect(0) first, then use Assembly.GetExecutingAssembly().GetName().Name to get the assembly name. typeof(string).FullName gives the full type name. For CityResource, implement IDisposable with a Dispose() method that prints the message, then use `using (var r = new CityResource()) { }` to auto-dispose it.
main.py
Hi! I'm Rex 👋
Output
Ready. Press ▶ Run or Ctrl+Enter.