Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close

    Module 1 · Values, Parameters and Byrefs · Lesson 1 of 34

    A value is not a variable, and assignment vs ref assignment

    1.1 A value is not the same thing as a variable

    The value 42 is an abstract number. A variable is a typed storage location that can currently contain the bit pattern representing 42. Two variables may contain equal values while occupying different storage. A reference variable is different again: it stores a reference to another variable, called its referent, rather than storing the referent’s value directly.[S1]

    Four terms that must stay separate

    • Value
    • The information being represented, such as the integer 42 or a Point with coordinates.
    • Variable
    • A typed storage location whose current contents form a value.
    • Object reference
    • A GC-tracked reference identifying a managed object. Copying it does not copy the object.
    • Managed byref
    • A GC-aware reference to a variable or interior storage location. In IL signatures it is written as T&.

    Equal values, different storage

    stack framestack frame
    a: int = 42x: int = 42
    b: int = 42r: ref int
    a = b copies 42 into ar = 99 writes into x
    no alias existsx and r observe the same bytes

    1.2 Assignment and ref assignment are different operations

    Normal assignment changes the value stored in the destination. Ref assignment changes which storage location a reference variable aliases.

    C#
    int[] numbers = [10, 20, 30];
    ref int slot = ref numbers[0]; // slot aliases element 0
    slot = 111;
    // ordinary assignment: numbers[0] = 111
    slot = ref numbers[2];
    // ref assignment: alias now targets element 2
    slot = 333;
    // ordinary assignment: numbers[2] = 333

    After the code runs, the array is [111, 20, 333]. The expression slot = 333 does not replace the alias; it writes through the alias. The expression slot = ref numbers[2] changes the alias itself.

    Under The Hood

    • CLR / IL. The CLI type system has managed pointer types, written T&. Address-producing instructions include ldloca for a local, ldarga for an argument, ldflda for a field, and ldelema for an array element. Indirection instructions such as ldind.i4 and stind.i4 read and write through the managed pointer.[S8]
    • JIT / CPU. A live byref is normally represented by a machine-sized address-like value in a register or stack slot. It introduces aliasing: the JIT may need to assume that a store through the byref changes another value whose address could overlap.
    • Memory layout. A byref can target stack storage, an argument, an array element, or a field inside a managed object. It is not an object header and does not carry a MethodTable pointer of its own.
    • GC impact. A managed byref into the managed heap is reported as an interior GC pointer. The GC can keep the containing object alive and account for relocation; the byref does not automatically pin the object.[S9][S13]
    • Performance cost. Creating an alias normally allocates no managed object. Costs are indirect access, possible register pressure, and optimization restrictions caused by uncertain aliasing.
    • Naive mental model
    • “ref means C-style pointer, so the object is pinned and I can do arbitrary address arithmetic.”
    • Accurate mental model
    • A C# byref is a typed, GC-aware alias whose uses and lifetime are constrained by the compiler and verifier. It can point into movable managed memory without granting arbitrary pointer arithmetic.
    • Explain it in one sentence
    • What is the difference between slot = value; and slot = ref other;?
    Sign in to mark lessons done and keep your place in the course.Sign in