My understanding is that the reason why there are raw types and type erasure in Java is that because at the time generics was introduced, there were standard APIs that could not be made generic without breaking existing code.
Generics was also introduced to .NET at some point down the road, but this feature was implemented in a manner that does not rely on raw types or type erasure (and if it does, it does so in a manner that is transparent to the user). So existing APIs remained unchanged (for example, the code in the System.Collections namespace) and new, generic APIs were introduced (for example, the code in the System.Collections.Generic namespace).
So how come Java generics, unlike .NET generics, requires raw types / type erasure?
.Net introduced generics by changing the bytecode language, virtual machine, and JITter to recognize generic types.
This was an enormous amount of work that took about two years.
Java introduced generics as a purely compile-time feature, with only small runtime changes (new metadata and reflection APIs).
This was a much simpler task, and it maintained backwards compatibility with older runtimes, but it's much more annoying to work with.