$ dotnet runAge cannot be negativedonestackMain · a: not setCheckAge · age = -5heapMessage "Age cannot be negative"StackTrace CheckAge ← MainArgumentException1try {2 int a = CheckAge(-5);3 Console.WriteLine(a);4} catch (ArgumentException e) {5 Console.WriteLine(e.Message);6} finally {7 Console.WriteLine("done");8}skipped1static int CheckAge(int age) {2 if (age < 0)3 throw new ArgumentException(4 "Age cannot be negative");5 return age;6}skippedcallMessagedone
Front row: the code (Program.cs and CheckAge)Back row: the console, the call stack and the heapTokens: the call, the exception, the message and doneFront row: the top-level statements of Program.cs (a try with a catch and a finally) and the method CheckAge. Back row: the console, the call stack (one frame per unfinished call) and the heap. CheckAge(-5) pushes a frame, throws an ArgumentException onto the heap, and is unwound off the stack; Main's catch handles it, prints "Age cannot be negative", and finally prints "done". Struck-through lines never run. The call stack is drawn simply: one block per call holding its parameters and locals. Real frames also hold the return address and saved registers, and the JIT may keep small values in CPU registers instead.

The call

  1. An exception is an object that reports an error a method cannot fix where it happens. Throwing one stops the normal flow, and .NET looks for code that can handle it. Here, CheckAge refuses a negative age.

Throw and unwind

Catch and finally

What happens

// step 1/9 · idea
exception  an object of a class derived from System.Exception
           Message     what went wrong (text)
           StackTrace  where it happened (the chain of calls)
throw      stops the method at once
try/catch  marks the code that can handle it

The call stack is drawn simply: one block per call holding its parameters and locals. Real frames also hold the return address and saved registers, and the JIT may keep small values in CPU registers instead. If no catch anywhere on the stack matches, the exception is unhandled: .NET ends the process and prints "Unhandled exception." with the type, message and stack trace to standard error. For an unhandled exception, Microsoft does not guarantee that finally blocks run.