Type erasure has ups as well as downs. For one, it means you can write runtime polymorphic code when you don't care about static types - something that requires extra effort and a non-generic base type in .net. Any time you pass an object through a runtime polymorphic "hole" (e.g. a location of type java.lang.Object / System.Object), you lose the ability to pass along type parameters. In .net, if you don't have that abstract base class / interface, your only fallback is reflection. In Java, you've got List<?> or whatever it is.