$ dotnet run42 himemorya.Valueb.ValuensT = intValue : int✕ CS0029own codeBox<int>T = stringValue : string✕ CS0453shared codeBox<string>1Box<int> a = new(41);2Box<string> b = new("hi");3int n = a.Value + 1;4string s = b.Value;5Console.WriteLine($"{n} {s}");Roslyn1class Box<T>(T v)2{3 public T Value = v;4}intstringBox<int>Box<string>"oops"where T : struct41"hi"42"hi"42 hi01010101
Front row: the code (Program.cs, Roslyn, the Box<T> definition)Back row: console, memory and the constructed typesTokens: type arguments, values and machine code moving throughFront row, build time: Program.cs, the compiler Roslyn, and the generic definition Box<T>. Back row: the console, memory, and the constructed types Box<int> and Box<string>, made from the one definition. Each type argument replaces T; the compiler checks every use; at run time the values fill memory and 42 hi reaches the console. b.Value holds a reference to the string object "hi", shown here as its text. n and s are local variables, not on the heap; the figure puts them in one memory row for clarity.

Type parameters

  1. A box that holds one value is useful for any type. Writing IntBox and StringBox repeats the same code. One box of object fits everything but loses type checks and needs casts. Generics give both: one definition, fully typed.

Build: one definition, many types

Run: objects and code

What happens

// step 1/11 · why
class IntBox    { public int Value; }      copy 1
class StringBox { public string Value; }   copy 2, same code
class ObjBox    { public object Value; }   one class, but every read
                                           needs a cast: (int)box.Value
generic         class Box<T> ...           one class, every type, typed

class Box<T>(T v) uses a primary constructor (C# 12). The older form is a constructor written inside the class: public Box(T v) { Value = v; }. The CLR shares one copy of machine code among reference types because every reference is the same size. Each value type gets its own copy, so Box<int> stores and reads an int directly, without boxing.