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
42or aPointwith 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 frame | stack frame |
|---|---|
a: int = 42 | x: int = 42 |
b: int = 42 | r: ref int |
a = b copies 42 into a | r = 99 writes into x |
| no alias exists | x 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.
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 includeldlocafor a local,ldargafor an argument,ldfldafor a field, andldelemafor an array element. Indirection instructions such asldind.i4andstind.i4read 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;andslot = ref other;?