.NET Runtime Internals — The City's Maintenance Department
20 XPHard
Ctrl+Enter RunCtrl+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 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 references — WeakReference<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.