I suspect it’s a JITting problem. Currently, the JIT reuses the same generated code for all reference type arguments – so a List<string>
‘s vtable points to the same machine code as that of List<Stream>
. That wouldn’t work if each new T()
call had to be resolved in the JITted code.
Just a guess, but it makes a certain amount of sense.
One interesting little point: in neither case does the parameterless constructor of a value type get called, if there is one (which is vanishingly rare). See my recent blog post for details. I don’t know whether there’s any way of forcing it in expression trees.