Lessons in this course (11)
11. Exceptions, boxing, strings and other runtime behaviours
Exceptions inside the CLR: throw creates the exception object and captures the stack trace; the runtime does a two-pass unwind — first finds a matching catch (running exception filters when (...) without unwinding), then unwinds frames running finally blocks. Throwing is expensive (stack walk) — don't use exceptions for normal control flow. Unhandled exceptions on any thread terminate the process (after AppDomain.UnhandledException fires).
Boxing: converting a value type to object/interface allocates a heap object with a header and copies the value; unboxing type-checks and copies back. Generics avoid it.
Strings: immutable UTF-16 reference types; literals are interned (one instance per value per process); concatenation in loops creates garbage — use StringBuilder, string.Create, interpolation handlers, or Span<char>.
Type safety and verification: the CLR prevents treating memory as the wrong type; unsafe code with pointers opts out (requires AllowUnsafeBlocks).
Reflection and metadata: typeof(T).GetMethods() reads the assembly metadata at runtime — flexible but slow and AOT-unfriendly; source generators (System.Text.Json, logging, regex) do the work at compile time instead.
Interop: P/Invoke ([LibraryImport("user32.dll")] source-generated in .NET 7+, [DllImport] before) calls native functions with marshalling of parameters; COM interop for Office automation and legacy components.