Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close

    Module 1 · Variables, Types and Control Flow · Lesson 2 of 37

    Value vs reference semantics, and method call stack frames

    Value semantics and reference semantics are assignment rules

    One concept

    Value-type assignment copies data; reference-type assignment copies a reference to the same object.

    Why this matters in TaskFlow

    TaskFlow task objects will be passed around repositories, services, and UI code. Shared mutable objects can make a change appear in a completely different part of the system.

    Mental model

    Do not equate value type with stack or reference type with heap. The useful question is: what does assignment copy?

    A value-type slot contains the data. A reference-type slot contains a reference. Copying the reference creates two aliases to one object.

    MENTAL MODEL DIAGRAM

    value assignmentreference assignment
    priorityA [ 2 ]first [ ref 0xA ] --+
    priorityB [ 2 ]second [ ref 0xA ] --+--> TaskCard
    change B -> A unchangedmutate through second -> first observes it

    TaskFlow: bad vs good

    BAD - a copied reference is mistaken for a copied object

    C#
    TaskCard first = new("Fix export");
    TaskCard second = first;
    second.Title = "Delete production";
    Console.WriteLine(first.Title);

    GOOD - copy intent is explicit

    C#
    TaskCard first = new("Fix export");
    TaskCard second = new(first.Title);
    second.Title = "Write regression test";
    Console.WriteLine(first.Title); // Fix export
    
    public sealed class TaskCard(string title)
    {
     public string Title { get; set; } = title;
    }

    What beginners get wrong

    They say 'classes live on the heap' and stop thinking. That does not explain aliasing, boxing, fields inside objects, or compiler optimizations.

    What interviewers test

    Predict aliasing behavior, explain shallow versus deep copy, and avoid the false stack-versus-heap shortcut.

    What breaks in production

    One request mutates an object cached or shared by another request, producing race conditions, stale views, and audit records that no longer match the original command.

    Engineer question - answer before running code

    What exactly does TaskCard second = first copy, and how many TaskCard objects exist afterward?

    Mini refactor task

    Add a Copy method or copy constructor to TaskCard. Demonstrate that changing the copy does not alter the original.

    Constraint

    Copy only the state currently present. Do not introduce records yet; make object creation explicit.

    A method call creates a new stack frame story

    One concept

    Each active method call has its own logical frame containing parameters, locals, and a return point.

    Why this matters in TaskFlow

    When TaskFlow validation fails several calls deep, reading the stack trace depends on understanding who called whom and what each frame owned.

    Mental model

    Picture a stack of active conversations. The caller pauses at the call site. The callee receives parameter slots initialized from the arguments, creates local slots, and eventually returns a value or throws. The JIT may inline or optimize frames, but this model predicts source-level behavior and stack traces.

    MENTAL MODEL DIAGRAM

    Text
    top - currently running
    +----------------------------+
    | NormalizeTitle(title slot) |
    | local: trimmed             |
    +----------------------------+
    | CreateTask(rawTitle slot)  |
    | return point: line 12      |
    +----------------------------+
    | Main(args slot)            |
    +----------------------------+
    bottom - oldest active call

    TaskFlow: bad vs good

    BAD - hidden global state makes call behavior unclear

    C#
    static string _currentTitle = "";
    static void NormalizeTitle()
    {
     _currentTitle = _currentTitle.Trim();
    }

    GOOD - inputs and outputs tell the frame story

    C#
    static string NormalizeTitle(string rawTitle)
    {
     string trimmed = rawTitle.Trim();
     return trimmed;
    }
    string title = NormalizeTitle(" Fix export ");

    What beginners get wrong

    They think a method 'jumps away' without tracking argument copies, locals, return values, or which frame an exception is leaving.

    What interviewers test

    Trace a call chain, identify parameter values, and read a stack trace from the throw site outward to callers.

    What breaks in production

    Hidden shared state makes methods order-dependent, tests flaky, and concurrent calls overwrite each other's data.

    Engineer question - answer before running code

    When NormalizeTitle starts, which frame owns rawTitle, which frame owns title, and what happens when the method returns?

    Mini refactor task

    Draw the frames for Main -> CreateTask -> NormalizeTitle. Put each parameter and local in the correct frame, then mark the return path.

    Constraint

    Use only data visible in the method signatures. Do not invent global fields.

    Sign in to mark lessons done and keep your place in the course.Sign in