Stefan Matthias Aust
2004-06-09 06:52:04 UTC
Schon gesehen? ->
http://msdn.microsoft.com/vstudio/java/gettingstarted/csharpforjava/
Ein IMHO sehr interessanter Vergleich von Java und C#. Verglichen
werden Java 1.4 und C# 1.0. Hier meine Anmerkungen:
Es wird erwähnt, dass C# mehrere public toplevel classes in einer Datei
haben kann. Finde ich irrelevant, ich denke in und entwickle mit
Klassen, nicht Dateien. Dateien sind ein notwendiges Übel. Die starke
Bindung zwischen Klassenname und Dateinamen macht es IMHO einfacher,
ohne IDE die richtige Datei zu finden - wenigstens für public toplevel
classes.
Alias bei import ist nett, aber bis auf den unsäglichen Konflikt bei
awt/util.List und Date hatte ich bislang noch keine Probleme, auch wenn
es in der Theorie nett wäre, Namenskonflikte durch Umbenennen während
des Imports zu lösen.
Einen Präprozessor als Teil der Sprachdefinition halte ich für unnötig.
Diesen kann man, wenn man es benötigt, durch externe Werkzeuge nachrüsten.
Einen Finalizer mit Destruktor-Syntax zu notieren so wie C# es macht
halte ich für irreführend.
Bei den Datentypen hat C# in für Geschäftsanwendungen wichtigen Datentyp
"decimal". Diesen könnte man duch BigInteger bzw. BigDecimal bei Java
realisieren, aber wegen des fehlenden operator overloadings ist es
anstrengend, mit diesen Objekten zu arbeiten. C# hat operator
overloading. Warum es daher ein eigener primitiver Datentyp sein musste
erschließt sich mir nicht.
Automatisches Boxing und Unboxing - und damit eine Vereinheitlichung der
Typhierarchie von primitiven und Objekttypen bietet Java leider erst mit
1.5. Bis dahin ist das ein Plus-Punkt für C#. Zudem ist die CLR laut
einem kleinen inoffiziellen Benchmark von mir wesentlich schneller als
die 1.5 beta1...
Enums kommen ebenfalls erst mit 1.5. Noch ein Plus-Punkt für C#.
Strings können in C# mit == verglichen werden, was dafür übergeschrieben
wurde. Vermeidet sicherlich viele Anfängerfehler, macht es aber lästig,
wenn man tatsächlich die Referenzen vergleichen will
((object) "a") == ((object) "b")
was zumindest ich in Java häufig brauche, weil ich gerne (aus
Effizienzgründen - ich kann nicht anders) mit intern'ten String arbeite.
Ob es derartige Strings in C# gibt, wird nicht erwähnt und ich weiss
es gerade nicht.
Strings, in denen \ kein Escape ist mögen für Windows-Dateinamen und
Reguläre Ausdrücke eine Erleichterung bieten, sind aber IMHO nicht
wirklich wichtig.
C# hat "unsigned" Datentypen. Macht das Rechnen einfacher. Ich finde
aber inkonsequent, dass es sonst immer T und uT gibt nur bei byte ist es
anders herum und dort ist byte unsigned unt sbyte ist die
vorzeichenbehaftere Variante.
Die Unterscheidung zwischen Werttypen und Referenztypen bei C# (bzw. der
CLR) ist eine wichtige, insbesondere da man mit "struct" eigene
Werttypen definieren kann. Noch ein Pluspunkt für C#.
Ebenfalls hilfreich ist, dass wahlweise integer Berechnung nicht einfach
klamheimlich überlaufen und das Vorzeichen wechseln. Ich verstehe
nicht, warum das nicht standardmäßig einen Fehler gibt. Wahrscheinlich
weil sonst zu viele unwissende oder schlampige Programmierer merken
würden, dass sie fehlerhaften Code schreiben.
Der Sinn von typeof und sizeof von C# erschließt sich mir nicht. Was
unterscheidet ersteres von .getType() und beim zweiten Operator kann ich
doch einfach in der Spec nachgucken...
Switch ist IMHO besser gelöst als in Java und man hat sich von
C-Kompatibiliät gelöst, was an sich schon mal gut ist :) Noch ein
Pluspunkt.
foreach-Schleifen aus C# gibt es in Java ab 1.5.
Den Zugriffsmodifikator "internal" finde ich gelungener als Javas
"package" Sichtbarkeit, die, da auf ein Package beschränkt,
normalerweise zu klein ist und unnötig oft zu "public" zwingt. Auch die
Entscheidung, private als default zu nehmen finde ich besser. Noch ein
Plus-Punkt.
Das in C# (und der CLR) alle Methoden mit einem Großbuchstaben anfangen
finde ich jedenfalls sehr verwirend. Ich bin das seit Jahren anders
gewöhnt und finde es schwer, auf diese Weise zwischen Klassen,
Namensräumen und Methoden zu unterscheiden. Daher ist das für mich ein
dicker Minuspunkt.
Mehr Freiheit bei der Signatur der Main-Methoden bei C# finde ich auch
nicht erstrebenswert.
Call-by-reference für Variablen ist nett... noch besser hätte ich aber
gefunden, wenn die Sprachen Tupel-Typen hätten und demzufolge mehrfache
Rückgabewerte zulassen würde. Bietet dummerweise weder Java noch C#.
Variable Argumente direkt statt extra ein Object[] zu benutzen finde ich
da wesentlich wichtiger und brauche ich häufiger. Schön, dass C# das
kann. Java wird's ab 1.5 können.
Properties machen IMHO den Code lesbarer - allerdings zu dem Preis von
mehr Syntax und der ewigen Entscheidung - nehme ich eine parameterlose
Funktion oder doch ein Property...
C# hat echte mehrdimensionale Array - ein Vorteil gegenüber Java. Punkt.
Der Artikel erwähnt, dass ein C#-Array eine Sort-Methode hat. Schön.
In Java gibt es aber wenigstens java.util.Arrays mit derartigen
statischen Hilfsfunktionen. Das unterschlägt der Artikel...
Das man in C# überschriebene Methoden mit "override" kennzeichnen muss
finde ich gut. Das man "virtual" 'dranschreiben muss finde ich
schlecht. Das man dadurch auch Methoden mit gleichen Namen in
Unterklassen definieren kann, ebenfalls, da nur verwirrend. Covariante
Rückgabetypen, die in Java erst ab 1.5 und nur mit generischen Typen
gehen, hat C# jetzt schon.
Wie ich schon sagte, ich finde Operator-Overloading gut und finde
schade, dass Java das nicht bietet. Dumm ist aber, dass es Operatoren
überhaupt gibt. Schöner und eleganter wäre, wenn das einfach
syntaktischer Zucker für normale Methoden wäre. Das hat keine Sprache
begriffen und implementiert. Man muss da zu Lisp, Smalltalk, Python,
Ruby gucken.
Und wenn schon nicht Operator-Overloading generell, dann wäre ich
glücklich wenn nur der Index-Operator [] überschreibbar wäre. Ein
map["Hallo"] = map["Welt"]
finde ich so viel besser und einheitlicher als
integerArray[0]
string.charAt(0)
list.get(0)
map.get(0)
was in Java nötig ist. Warum hat man eigentlich bei List und Map den
selben Namen gewählt? Ist das nicht inkonsequent in der Inkonsequenz?
Exceptions in C# sind niemals checked. Ich könnte damit leben. Ob es
ein Vorteil oder doch Nachteil ist, kann ich nicht sagen - tendiere aber
zu einem Vorteil, weil ich doch zu häufig in Java schon "normale"
Exceptions in Runtime-Exceptions verpacken musste, nur um sie durch
vordefinierte Interfaces zu schleusen.
Den kleinen Bruder von Attributen (Metadaten) bekommt Java mit 1.5.
Delegates sind IMHO elegant. Dafür hat Java anonyme innere Klassen, die
bei C# fehlen. Brauchbar wird C# 2.0, das closures haben soll... Das
lässt Java 1.5 vermissen.
In C# kann man Regionen als Unsafe erklären und dann mit Pointer
spielen, sodass jeder C-Entwickler neidisch werden kann. Das mag für
bestimmte Fälle hilfreich sein, ist aber natürlich tödlich für
plattformübergreifende Entwicklungen. Auch kann man sich damit u.U. die
allerseits beliebten Buffer-Overrun-Exploits einhandeln. Zumindest kann
man per Security-Einstellungen festlegen, ob Programme mit
unsafe-Einschlüssen gestartet werden dürfen oder nicht.
Was der Artikel nicht erwähnt ist PInvoke, eine Funktion, um einfach
DLLs aufzurufen. Auch nicht wirklich plattformübergreifend, aber doch
bei Mono z.B. der Grund, warum es schnell sehr viele existierende
Linux-Bibliotheken angebunden wurden konnten und deutlich bequemer als
der Krampf bei Java, jedes Mal den C-Compiler hervorzuholen und soll
blöde Glue-DLLs selbst zu schreiben. Etwas wie PInvoke kann man
natürlich auch in Java realisieren und es gibt IMHO Anbieter von
vergleichbaren Lösungen für Java.
Fazit: Die Sprache C# ist deutlich größer und komplexer und bietet
dafür einige interessante Zusatzfeatures. Diese alleine halte ich
alleridngs nicht für produktivitätssteigend. Die Produktivität mache
ich eher an der IDE fest und da kann ich jetzt keinen Vergleich von z.B.
Eclipse zu VS.NET anstellen. Ich würde allerdings unterstellen, dass
die fehlenden Refactorings bei VS.NET produktivitätshemmend sind. Eine
IDE wie SharpDevelop hat in meinen Augen keine Chance gegen etwas wie
Eclipse oder IDEA. Wer auf mehrdimensionale Array und Werttypen
angewiesen ist - etwa für komplexe mathematische Berechnungen - der ist
mit C# besser 'dran als mit Java. Ansonsten sind die einzelnen Features
nicht so wichtig. Einzig das erweiterte switch und die gotos habe ich
einmal zu schätzen gelernt. Es ist damit sehr einfach, Parser mittels
Generator zu bauen während man bei Java echt schleußlichen Code mit
benannten Schleifen erzeugen muss und zudem noch mit der 64K-Grenze der
VM kämpfen muss.
Die Klassenbibliotheken vergleicht der Artikel gar nicht - gerade hier
liegt aber IMHO die Mächtigkeit der Sprachen. Tatsächlich haben mir
eigentlich beide Sprachen viel zu viel Syntax und mindestens die hälfte
aller Features sollte lieber in der Klassenbibliothek liegen (etwa alle
Datentypen) und dafür sollte die Sprache lieber erweiterbar und
generischer sein. Das entspricht aber wohl nicht dem C-Erbe und ist
vielleicht auch laut Ansicht der Sprachentwickler zu
modern/exotisch/unheimlich, keine Ahnung...
Java 1.5 gleicht die meisten Sprachdefizite von Java gegenüber C# aus.
Allerdings wird auch hier aufgerüstet und C# 2.0 soll einige
interessante Neuerungen bieten - und die Sprache noch komplexer machen.
Dank closures wird C# erstmalig in die Austsche "languages which does
not suck immediately"-Kategorie aufgenommen werden können. Polymophe
Typen (aka generics) wird es auch geben - zusammen mit dem Versprechen,
dass diese im Gegensatz zu Java auch für primitive aka Wert-Datentypen
funktionieren. Iteratoren sind deutlich besser als in Java und es wird
"nullable"-Typen geben, also ein int, das auch keinen Wert haben kann -
Kompatibilität zu Datenbank, yeah. Hätte man ganz ohne primitive Typen
natürlich automatisch, aber das sieht wohl man wieder keiner... so ganz
habe ich aber vielleicht die doch recht lange Spec noch nicht verstanden.
bye
http://msdn.microsoft.com/vstudio/java/gettingstarted/csharpforjava/
Ein IMHO sehr interessanter Vergleich von Java und C#. Verglichen
werden Java 1.4 und C# 1.0. Hier meine Anmerkungen:
Es wird erwähnt, dass C# mehrere public toplevel classes in einer Datei
haben kann. Finde ich irrelevant, ich denke in und entwickle mit
Klassen, nicht Dateien. Dateien sind ein notwendiges Übel. Die starke
Bindung zwischen Klassenname und Dateinamen macht es IMHO einfacher,
ohne IDE die richtige Datei zu finden - wenigstens für public toplevel
classes.
Alias bei import ist nett, aber bis auf den unsäglichen Konflikt bei
awt/util.List und Date hatte ich bislang noch keine Probleme, auch wenn
es in der Theorie nett wäre, Namenskonflikte durch Umbenennen während
des Imports zu lösen.
Einen Präprozessor als Teil der Sprachdefinition halte ich für unnötig.
Diesen kann man, wenn man es benötigt, durch externe Werkzeuge nachrüsten.
Einen Finalizer mit Destruktor-Syntax zu notieren so wie C# es macht
halte ich für irreführend.
Bei den Datentypen hat C# in für Geschäftsanwendungen wichtigen Datentyp
"decimal". Diesen könnte man duch BigInteger bzw. BigDecimal bei Java
realisieren, aber wegen des fehlenden operator overloadings ist es
anstrengend, mit diesen Objekten zu arbeiten. C# hat operator
overloading. Warum es daher ein eigener primitiver Datentyp sein musste
erschließt sich mir nicht.
Automatisches Boxing und Unboxing - und damit eine Vereinheitlichung der
Typhierarchie von primitiven und Objekttypen bietet Java leider erst mit
1.5. Bis dahin ist das ein Plus-Punkt für C#. Zudem ist die CLR laut
einem kleinen inoffiziellen Benchmark von mir wesentlich schneller als
die 1.5 beta1...
Enums kommen ebenfalls erst mit 1.5. Noch ein Plus-Punkt für C#.
Strings können in C# mit == verglichen werden, was dafür übergeschrieben
wurde. Vermeidet sicherlich viele Anfängerfehler, macht es aber lästig,
wenn man tatsächlich die Referenzen vergleichen will
((object) "a") == ((object) "b")
was zumindest ich in Java häufig brauche, weil ich gerne (aus
Effizienzgründen - ich kann nicht anders) mit intern'ten String arbeite.
Ob es derartige Strings in C# gibt, wird nicht erwähnt und ich weiss
es gerade nicht.
Strings, in denen \ kein Escape ist mögen für Windows-Dateinamen und
Reguläre Ausdrücke eine Erleichterung bieten, sind aber IMHO nicht
wirklich wichtig.
C# hat "unsigned" Datentypen. Macht das Rechnen einfacher. Ich finde
aber inkonsequent, dass es sonst immer T und uT gibt nur bei byte ist es
anders herum und dort ist byte unsigned unt sbyte ist die
vorzeichenbehaftere Variante.
Die Unterscheidung zwischen Werttypen und Referenztypen bei C# (bzw. der
CLR) ist eine wichtige, insbesondere da man mit "struct" eigene
Werttypen definieren kann. Noch ein Pluspunkt für C#.
Ebenfalls hilfreich ist, dass wahlweise integer Berechnung nicht einfach
klamheimlich überlaufen und das Vorzeichen wechseln. Ich verstehe
nicht, warum das nicht standardmäßig einen Fehler gibt. Wahrscheinlich
weil sonst zu viele unwissende oder schlampige Programmierer merken
würden, dass sie fehlerhaften Code schreiben.
Der Sinn von typeof und sizeof von C# erschließt sich mir nicht. Was
unterscheidet ersteres von .getType() und beim zweiten Operator kann ich
doch einfach in der Spec nachgucken...
Switch ist IMHO besser gelöst als in Java und man hat sich von
C-Kompatibiliät gelöst, was an sich schon mal gut ist :) Noch ein
Pluspunkt.
foreach-Schleifen aus C# gibt es in Java ab 1.5.
Den Zugriffsmodifikator "internal" finde ich gelungener als Javas
"package" Sichtbarkeit, die, da auf ein Package beschränkt,
normalerweise zu klein ist und unnötig oft zu "public" zwingt. Auch die
Entscheidung, private als default zu nehmen finde ich besser. Noch ein
Plus-Punkt.
Das in C# (und der CLR) alle Methoden mit einem Großbuchstaben anfangen
finde ich jedenfalls sehr verwirend. Ich bin das seit Jahren anders
gewöhnt und finde es schwer, auf diese Weise zwischen Klassen,
Namensräumen und Methoden zu unterscheiden. Daher ist das für mich ein
dicker Minuspunkt.
Mehr Freiheit bei der Signatur der Main-Methoden bei C# finde ich auch
nicht erstrebenswert.
Call-by-reference für Variablen ist nett... noch besser hätte ich aber
gefunden, wenn die Sprachen Tupel-Typen hätten und demzufolge mehrfache
Rückgabewerte zulassen würde. Bietet dummerweise weder Java noch C#.
Variable Argumente direkt statt extra ein Object[] zu benutzen finde ich
da wesentlich wichtiger und brauche ich häufiger. Schön, dass C# das
kann. Java wird's ab 1.5 können.
Properties machen IMHO den Code lesbarer - allerdings zu dem Preis von
mehr Syntax und der ewigen Entscheidung - nehme ich eine parameterlose
Funktion oder doch ein Property...
C# hat echte mehrdimensionale Array - ein Vorteil gegenüber Java. Punkt.
Der Artikel erwähnt, dass ein C#-Array eine Sort-Methode hat. Schön.
In Java gibt es aber wenigstens java.util.Arrays mit derartigen
statischen Hilfsfunktionen. Das unterschlägt der Artikel...
Das man in C# überschriebene Methoden mit "override" kennzeichnen muss
finde ich gut. Das man "virtual" 'dranschreiben muss finde ich
schlecht. Das man dadurch auch Methoden mit gleichen Namen in
Unterklassen definieren kann, ebenfalls, da nur verwirrend. Covariante
Rückgabetypen, die in Java erst ab 1.5 und nur mit generischen Typen
gehen, hat C# jetzt schon.
Wie ich schon sagte, ich finde Operator-Overloading gut und finde
schade, dass Java das nicht bietet. Dumm ist aber, dass es Operatoren
überhaupt gibt. Schöner und eleganter wäre, wenn das einfach
syntaktischer Zucker für normale Methoden wäre. Das hat keine Sprache
begriffen und implementiert. Man muss da zu Lisp, Smalltalk, Python,
Ruby gucken.
Und wenn schon nicht Operator-Overloading generell, dann wäre ich
glücklich wenn nur der Index-Operator [] überschreibbar wäre. Ein
map["Hallo"] = map["Welt"]
finde ich so viel besser und einheitlicher als
integerArray[0]
string.charAt(0)
list.get(0)
map.get(0)
was in Java nötig ist. Warum hat man eigentlich bei List und Map den
selben Namen gewählt? Ist das nicht inkonsequent in der Inkonsequenz?
Exceptions in C# sind niemals checked. Ich könnte damit leben. Ob es
ein Vorteil oder doch Nachteil ist, kann ich nicht sagen - tendiere aber
zu einem Vorteil, weil ich doch zu häufig in Java schon "normale"
Exceptions in Runtime-Exceptions verpacken musste, nur um sie durch
vordefinierte Interfaces zu schleusen.
Den kleinen Bruder von Attributen (Metadaten) bekommt Java mit 1.5.
Delegates sind IMHO elegant. Dafür hat Java anonyme innere Klassen, die
bei C# fehlen. Brauchbar wird C# 2.0, das closures haben soll... Das
lässt Java 1.5 vermissen.
In C# kann man Regionen als Unsafe erklären und dann mit Pointer
spielen, sodass jeder C-Entwickler neidisch werden kann. Das mag für
bestimmte Fälle hilfreich sein, ist aber natürlich tödlich für
plattformübergreifende Entwicklungen. Auch kann man sich damit u.U. die
allerseits beliebten Buffer-Overrun-Exploits einhandeln. Zumindest kann
man per Security-Einstellungen festlegen, ob Programme mit
unsafe-Einschlüssen gestartet werden dürfen oder nicht.
Was der Artikel nicht erwähnt ist PInvoke, eine Funktion, um einfach
DLLs aufzurufen. Auch nicht wirklich plattformübergreifend, aber doch
bei Mono z.B. der Grund, warum es schnell sehr viele existierende
Linux-Bibliotheken angebunden wurden konnten und deutlich bequemer als
der Krampf bei Java, jedes Mal den C-Compiler hervorzuholen und soll
blöde Glue-DLLs selbst zu schreiben. Etwas wie PInvoke kann man
natürlich auch in Java realisieren und es gibt IMHO Anbieter von
vergleichbaren Lösungen für Java.
Fazit: Die Sprache C# ist deutlich größer und komplexer und bietet
dafür einige interessante Zusatzfeatures. Diese alleine halte ich
alleridngs nicht für produktivitätssteigend. Die Produktivität mache
ich eher an der IDE fest und da kann ich jetzt keinen Vergleich von z.B.
Eclipse zu VS.NET anstellen. Ich würde allerdings unterstellen, dass
die fehlenden Refactorings bei VS.NET produktivitätshemmend sind. Eine
IDE wie SharpDevelop hat in meinen Augen keine Chance gegen etwas wie
Eclipse oder IDEA. Wer auf mehrdimensionale Array und Werttypen
angewiesen ist - etwa für komplexe mathematische Berechnungen - der ist
mit C# besser 'dran als mit Java. Ansonsten sind die einzelnen Features
nicht so wichtig. Einzig das erweiterte switch und die gotos habe ich
einmal zu schätzen gelernt. Es ist damit sehr einfach, Parser mittels
Generator zu bauen während man bei Java echt schleußlichen Code mit
benannten Schleifen erzeugen muss und zudem noch mit der 64K-Grenze der
VM kämpfen muss.
Die Klassenbibliotheken vergleicht der Artikel gar nicht - gerade hier
liegt aber IMHO die Mächtigkeit der Sprachen. Tatsächlich haben mir
eigentlich beide Sprachen viel zu viel Syntax und mindestens die hälfte
aller Features sollte lieber in der Klassenbibliothek liegen (etwa alle
Datentypen) und dafür sollte die Sprache lieber erweiterbar und
generischer sein. Das entspricht aber wohl nicht dem C-Erbe und ist
vielleicht auch laut Ansicht der Sprachentwickler zu
modern/exotisch/unheimlich, keine Ahnung...
Java 1.5 gleicht die meisten Sprachdefizite von Java gegenüber C# aus.
Allerdings wird auch hier aufgerüstet und C# 2.0 soll einige
interessante Neuerungen bieten - und die Sprache noch komplexer machen.
Dank closures wird C# erstmalig in die Austsche "languages which does
not suck immediately"-Kategorie aufgenommen werden können. Polymophe
Typen (aka generics) wird es auch geben - zusammen mit dem Versprechen,
dass diese im Gegensatz zu Java auch für primitive aka Wert-Datentypen
funktionieren. Iteratoren sind deutlich besser als in Java und es wird
"nullable"-Typen geben, also ein int, das auch keinen Wert haben kann -
Kompatibilität zu Datenbank, yeah. Hätte man ganz ohne primitive Typen
natürlich automatisch, aber das sieht wohl man wieder keiner... so ganz
habe ich aber vielleicht die doch recht lange Spec noch nicht verstanden.
bye
--
Stefan Matthias Aust // "Zweifel sind der Ansporn des Denkens..." -U
Stefan Matthias Aust // "Zweifel sind der Ansporn des Denkens..." -U