Java on the other hand had an implementation of generics that made Container<X> just a Container so you could mix your old containers with generic containers.
Now Java's approach used type erasure and had some limitations, but the C# incompatibility made me suffer every day, that's the cultural difference between Java and a lot of other languages.
It's funny because when I am coding Java and thinking just about Java I really enjoy the type system and rarely feel myself limited by type erasure and when I do I can unerase types easily by
- statically subclassing GenericType<X> to GenericType<ConcreteClass>
- dynamically by adding a type argument to the constructor
- mangling names (say you're writing out stubs to generate code to call a library, you can't use polymorphism to differentiate between
Expression<Result> someMethod(Expression<Integer> x)
and Expression<Result> someMethod(Expression<Double> x)
since after erasure the signature is the same so you just gotta grit your teeth and mangle the method names)but whenever I spend some time coding hard in a language that doesn't erase generic parameters I come back and I am not in my comfortable Java groove and it hurts.