Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close

    Module 1 · Value and Reference Types · Lesson 1 of 18

    How to use this lesson

    How to use this lesson

    This is not a memorization handout. It is a guided model-building exercise. Read one section, run the code, redraw the memory picture from memory, and then explain the result aloud. If your explanation uses the words “it just does that,” the model is not yet complete.

    Recommended learning loop

    1. Predict first. Before reading an output or diagram, write what you expect.
    2. Trace the bits. Ask: what exact value is copied, and where is the destination storage?
    3. Inspect lower layers. Compare C# semantics, representative IL, and likely JIT behavior.
    4. Measure. Use BenchmarkDotNet only after you can state a hypothesis.
    5. Teach it back. Explain the concept without saying “structs are on the stack.”

    Interactive PDF notes

    The contents page, references, and navigation links are clickable. Quiz and exercise areas are fillable in viewers that support AcroForm fields, such as Adobe Acrobat and many browser PDF viewers. The fields also leave visible blank space when printed.

    Scope boundary

    This lesson deliberately masters one foundation: value semantics versus reference semantics, and how those semantics relate to storage. Boxing, ref/in/out, ref struct, string interning, and advanced GC behavior are introduced only where they clarify this model. They receive dedicated lessons later.

    Mastery gate

    Do not continue to Lesson 2 until you can answer all four questions without guessing:

    • What does a variable of a value type contain?
    • What does a variable of a reference type contain?
    • Why can a struct live inside a heap object?
    • Why is a reference-type parameter still passed by value unless marked ref, in, or out?

    Contents

    • How to use this lesson
    • The first-principles machine model
    • 1.1 Bits, bytes, addresses, and typed storage
    • 1.2 A process and its important memory regions
    • 1.3 The two questions you must keep separate
    • Value types: the variable contains the value
    • 2.1 A minimal copy experiment
    • 2.2 “Copy the value” means field-wise value semantics
    • 2.3 A value can contain references
    • Reference types: the variable contains a reference
    • 3.1 A minimal aliasing experiment
    • 3.2 Reference type does not mean “passed by reference”
    • The stack-vs-heap truth
    • 4.1 The accurate rule: value types are stored inline
    • 4.2 A struct inside a class lives inside the heap object
    • 4.3 A value-type array is a heap object with inline elements
    • 4.4 new does not mean “heap”
    • 4.5 The JIT may choose registers, stack slots, or no storage
    • Under The Hood
    • 5.1 Compilation pipeline: C# to CPU instructions
    • 5.2 IL evaluation stack is not the thread stack
    • 5.3 Representative IL: copying a struct
    • 5.4 Representative IL: copying a class reference
    • 5.5 Likely native-level work
    • 5.6 CoreCLR object layout on a typical 64-bit runtime
    • 5.7 What the MethodTable represents
    • 5.8 Array layout: value elements versus reference elements
    • 5.9 GC roots and why reference location matters
    • 5.10 Value types and GC scanning
    • 5.11 Write barriers: not every reference store costs the same
    • 5.12 Generations and the LOH preview
    • A precise storage matrix
    • Boxing: when a value becomes an object
    • Bad versus good type design
    • 8.1 Case A: millions of independent coordinates
    • 8.2 Case B: a mutable bank account with identity
    • The large-struct trap and by-reference passing preview
    • 10 Common myths dismantled
    • 11 Worked trace: one program, every layer
    • 11.1 Step 1: two independent coordinate values
    • 11.2 Step 2: one marker object, two aliases
    • 11.3 Step 3: replace the second value
    • 11.4 Step 4: assign the value into the aliased object
    • 12 Decision framework: struct or class?
    • 12.1 Prefer a value type when
    • 12.2 Prefer a reference type when
    • 13 Quiz - answer before checking code
    • 14 Coding exercise - build and explain
    • 15 Performance challenge - BenchmarkDotNet
    • 15.1 Setup
    • 15.2 Before running: write a falsifiable prediction
    • 15.3 Record your result
    • 15.4 Analysis questions
    • 16 Mastery checklist and teach-back template
    • A Appendix A - compact reference sheet
    • A.1 One-line definitions
    • A.2 Fast prediction algorithm
    • A.3 ASCII templates
    • B Appendix B - source and further reading

    m2.Position = second; copies the coordinate fields into the Position field inside the one shared Marker object. Because m1 and m2 alias that object, reading through either reference sees the updated inline field.

    Final state

    Managed heap

    Text
    +--------------------------------+
    | first
    | { X=1, Y=2 }
    |
    | Marker object
    |
    | second { X=9, Y=2 }
    |
    | Position { X=9, Y=2 }
    |
    | m1 ref -----------------+------------>| Name ref ---> "A"
    |
    | m2 ref -----------------+------------>|
    |
    +--------------------------------+

    Core idea

    There are three coordinate values in this story: first, second, and the inline Position field. There is one marker object and two references to it.

    stack slot. Source-level lexical scope is not a promise about physical memory residence.

    Under the hood note

    The JIT also computes GC liveness. A reference local can stop being reported as a GC root before the closing brace if the JIT proves it will not be used again. Conversely, optimizations can keep values alive in registers. The source code gives semantics, not a fixed memory photograph for every instruction.

    Lesson thesis

    Type category answers a semantic question. Storage location answers a placement question. They are related, but they are not the same question.

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