Precies! Maar MSIL is specifiek bedacht en ontworpen om naar toe te compileren, niet om met de hand zelf te schrijven. Het is dit uitgangspunt waardoor je MSIL beter kunt _beschouwen_ als specifiek datatype, dan als programmeertaal. Het moest makkelijk te parsen, makkelijk te generen en makkelijk te optimalizeren zijn. Het hoeft niet makkelijk te zijn om in te programmeren.
Het is niet moeilijk voor te stellen dat het schrijven van een optimizer voor een minimale taal zoals MSIL makkelijker is, dan voor een specifieke syntax-door-drenkte taal ala VB of C#. Zo'n optimizer werkt dan ook meteen voor _alle_ .Net talen. CLR is gewoon z'n binaire zusje, waar de operands door byte-codes zijn vervangen.
De vergelijking met JVM die sommige hier maken gaat een beetje mank: De JVM is een stuk minder krachtig.
Het kan bijvoorbeeld dynamisch linken als het geinterpreteerd wordt, maar het zou nooit dynamisch libraries kunnen linken die al naar machiene taal gecompileerd zijn. Je kan in theorie Java wel naar machiene taal compileren (er bestaan bijvoorbeeld speciale versies van Eclipse), maar dan worden het monolitische executables die geheel op zichzelf staan. Dus stel dat programma A, library C ergens eventjes gebruikt, dan moet hij in gecompileerde code
1) de gecompileerde code van library C bevatten
2) bij elke update van library C, opnieuw programma A compileren
3) bij elke update van library C, opnieuw programma A distributeren naar al je klanten
.NET kan dus voor machiene executable (een .EXE onder windows) toch nog de volgende features bieden:
1) dynamische linking
2) seperate compiling
En dat maakt .NET ideaal voor het bouwen van evolutionair product zoals een Operating Systeem en superieur aan de JVM.
Daarnaast is de JVM hartstikke crippeled in het type systeem. Puur de aanwezigheid van de cast operator in Java verraad al dat het type-systeem een lachertje is. Op elke plek waar een cast staat ga je van compile-time-type checking naar dynamische-type-checking. Dit is onnodig en heeft de volgende nadelen:
1) sommige fouten zullen pas boven komen drijven bij een bepaald soort gebruik van je applicatie. Als jij het test doe het het, maar als de klant het gebruikt krijg je opeens een run-time-exception.
2) om toch type-safety te garanderen, gaan we gedurende run-time de types controleren: dit kost CPU! Een cast in een inner-loop maakt Java van Just-in-Time-achtige-performance naar Is-dit-Qbasic-performance?
Daarnaast kent de JVM het probleem dat het zich tijdens start-up-time tegen hostile-code beschermt ipv tijdens compile-time. Daardoor starten al die Java programma's ook zo kut op: eerst wordt ff gecontroleerd of de code 'veilig' is, wat ok is voor een applet die je 1 keer gebruikt op een of andere website, maar niet voor applicaties die je installeert, en vier keer per dag opstart. Met .NET zou je (in theorie) kunnen compileren tijdens installatie: en dus op dat moment de code evalueren tegen misbruik.
Eind-conclusie: .NET is een stuk krachtiger dan de JVM.
PS. Ik moet wel opmerken dat inmiddels het type systeem van Java zelf verbeterd is:
http://java.sun.com/j2se/...de/language/generics.html
(of dit ook op het niveau van de JVM opgelost is in mij onduidelijk: ik ben bang dat achter de schermen nog steeds casts plaats vinden: met alle run-time-performance problemen die dat oplevert)
Talen zoals Haskell (met de GHC extensies) en sommige ML varianten konden dit soort geintjes al tijden, maar toen noemde alle (*vul hier een eufenisme voor dom in*) programmeurs gewoon alles wat ze niet snapte AI. Maar daar heeft 't weinig mee te maken! Overigs was dit al enigzins mogelijk voor de die-hards in C++ zonder type-checking dmv templates :-)
Maar laat je niet misleiden door de term generics. Dat is het namelijk niet: het is type-polymorphie! Hier is dezelfde toelichting van Microsoft over het onderwerp, die wat eerlijker zijn over hoe het gemarketeerd wordt en hoe het eigenlijk heet en waar het vandaan komt:
http://research.microsoft.com/projects/clrgen/.
Echte generics betekent dat je zowel polymorfische functies, polymorfische types, alswel type-indexed functies hebt. Zodat je polymorphische sorteer routine automatisch met al je eigen abstracte datatypes werkt, zonder dat je ooit een comparision-routine hoeft te defineren. Er zal slechts een comparision-routine voor de core-types nodig zijn. En dat dan allemaal met compile-time-type-safety: zodat er geen run-time-exceptions mogelijk zijn in code die geen IO doet, en er tijdens run-time geen type-informatie opgeslagen hoeft te zijn, wat weer performance winst oplevert. Laat het je uitleggen:
http://en.wikipedia.org/wiki/Generic_programming