skipnothing/.NET Platform

How Generics Work

Put `int` between the angle brackets of `List<int>` and that choice does not evaporate when you hit Build: you can ask the running program what it was and get `System.Int32` back, something Java cannot do.

  • The <int> in List<int> is still there when the program runs: reflection answers System.Int32, where Java erased it.
  • Reference-type versions of a generic share one compiled body; each value-type version gets its own machine code.
  • List<int> keeps raw ints inline in an int[] and never boxes; ArrayList boxes every value you add.
BUILDS ON
01

The type argument survives to run time

The previous topic ended on a warning: a value type used where an object is expected gets boxed, a hidden allocation on a line with no new. Generic collections are the standard cure, and to see why the cure works you first have to see what the angle brackets leave behind.

Write List<int> and the int is not a compile-time note that gets thrown away. Ask for it while the program runs:

Type t = typeof(List<int>);
Console.WriteLine(t.GetGenericArguments()[0]);   // System.Int32

The answer comes back System.Int32. The <int> is still bolted to the type, readable by reflection, available to serializers and anything else that needs to know what T actually is.

Java made the opposite call. There, new ArrayList<String>().getClass() and new ArrayList<Integer>().getClass() return the *same* class object: the <String> and <Integer> are erased before the program runs, so nothing can tell the two apart afterward. Same source shape, opposite answer. That one difference is the foundation the rest of this topic is built on.

ONE QUESTION, TWO ANSWERS

Keep going, sign up to unlock the rest

3 more parts in this topic, plus 25+ more topics in .NET Platform.

Sign up, it's freeSee the full .NET Platform
Memory & the Type System0/6#8 The Garbage Collector
#10 Span<T> & Memory<T>