In other words, I can tar up a Java appserver, copy it to another machine, untar it, and run it. No GAC, no registry, no caspol, no mysterious .dlls. It's all right there. Usually ;)
Which side of the fence the compiler/runtime fence any given feature fails on is probably more a function of (human) resource pooling on the Microsoft managed languages teams than any technical constraints.
The "wrong level" corresponds to the goals and direction of the greater managed languages team. If the C# team wanted to implement every feature without any regard for the Visual Basic or F# team, they could. Clearly, they aren't going to do this because it creates wasted effort, inconsistency between languages, and maintainence complexity. Moreover, implementing on the wrong level has impact on performance and the developer experience.
I didn't mean to imply that they do the wrong thing because they are short on man power. On the contrary, they do the right thing because they are short on manpower.
Everything could be a compiler trick, but that doesn't mean everything should be. The managed languages teams here at Microsoft absolutely kick ass; they know what they are doing.
The biggest example I can think of is 'generics'. Java 'generics' are implemented using the compiler and JVM has no clue about them whereas CLR actually understands them and you get full reflection support for generic classes. Read this detailed article on Generics in Java vs C#:
http://www.jprl.com/Blog/archive/development/2007/Aug-31.htm...
I also like the utility of AppDomains supported by CLR.
Overall, I love .NET platform precisely because how all the modules (CLR, languages) are integrated with each other to give you a powerful tool set.
Other than JVM being portable, I don't know of a single case where JVM is superior to CLR. [Performance wise there is not a measurable difference between the two.]