CLR Generic Specialization: Value Types vs Reference Types
1Concept
When a generic `List<T>` is instantiated with a value type (`int`), RyuJIT compiles dedicated native machine code for that exact struct size. For reference types (`string`, `object`), all instances share a single unified canonical machine code implementation.
2Architecture Diagram
Generic Type `Processor<T>`:
├── Processor<int> ──> JIT emits specialized 4-byte native machine code
├── Processor<double> ──> JIT emits specialized 8-byte SSE machine code
└── Processor<string> ──> JIT emits canonical shared pointer code (Canon)
└── Processor<User> ── shares same code as Processor<string> (Saves RAM!)3Code Example
C# 13 & .NET 9
using System;
public class CacheStore<T>
{
private T _data;
public CacheStore(T data) => _data = data;
public T Value => _data;
}
public class GenericSpecializationDemo
{
public static void Main()
{
var intCache = new CacheStore<int>(42); // JIT specialized for int
var strCache = new CacheStore<string>("DOTNET"); // JIT Canon pointer shared
Console.WriteLine($"Int Value: {intCache.Value}");
Console.WriteLine($"String Value: {strCache.Value}");
}
}4Expected Output
Int Value: 42 String Value: DOTNET
5Key Takeaways
- ✓Value type generics incur zero boxing and run at raw native C speed.
- ✓Reference type generics share machine code, preventing code bloat in memory.
- ✓Static fields in generic classes are unique per closed generic type (`MyClass<int>.Count != MyClass<string>.Count`).