Was kann C# besser als Java?



  • Ich habe mir heute mal C# auf folgender Seite angeschaut:
    http://de.wikipedia.org/wiki/C-Sharp

    Und mußte feststellen, das C# im Prinzip eine Kopie von Java
    ist, nur da es Java ja schon gibt, wozu braucht man dann C#?

    Was soll an C# soviel besser sein?



  • Frager schrieb:

    Was soll an C# soviel besser sein?

    Wie Bashars Signatur so schoen sagt: better implies different

    C# ist eine Sprache fuer die .NET Plattform. Das Ganze ist Java-aehnlich, aber dennoch anders 🙂

    Der auffallendste Unterschied ist wohl, dass man fuer die .NET Plattform verschiedene Sprachen verwenden kann - bei Java ist man (wie der Name schon sagt) mehr oder weniger an Java gebunden.

    Was interessiert dich denn im speziellen?



  • Shade Of Mine schrieb:

    Der auffallendste Unterschied ist wohl, dass man fuer die .NET Plattform verschiedene Sprachen verwenden kann - bei Java ist man (wie der Name schon sagt) mehr oder weniger an Java gebunden.

    1. Ja, momentan kann man neben Java nur 189 andere Sprachen nutzen, um Java-Bytecode zu erzeugen: Programming Languages for the Java Virtual Machine

    2. Hä? Ein Unterschied zwischen Java und C# soll sein, dass man C# nicht verwenden muss?! Habe ich deine Aussage richtig verstanden?



  • Frager schrieb:

    Und mußte feststellen, das C# im Prinzip eine Kopie von Java
    ist, nur da es Java ja schon gibt, wozu braucht man dann C#?

    1. Man braucht C# nicht.

    2. Es gibt schon ein paar Unterschiede, wobei diese größtenteils nur syntaktischen Zucker darstellen, der einem hier und da mal ein paar Zeichen erspart: Properties, Operator Overloading,...!



  • Gregor schrieb:

    Operator Overloading,...!

    Das nennst du syntaktischen Zucker der nur Zeichen spart? Sowas kann doch nur von einem eingefleischten Javaiianer kommen 😉 .



  • MaSTaH schrieb:

    Das nennst du syntaktischen Zucker der nur Zeichen spart? Sowas kann doch nur von einem eingefleischten Javaiianer kommen 😉 .

    Naja, natürlich ist das meine persönliche Sichtweise. Ich halte ein

    c = a + b;
    

    statt einem

    c = a.add(b);
    

    für eine sehr geringe Veränderung. Das ändert nicht die Art, wie man programmiert, sondern erspart einem nur ein paar Zeichen. Gut, einige werden die erste Variante für besser lesbar halten, aber andere werden dafür die 2. Variante für besser halten. Da gibt es ja die verschiedensten Sichtweisen. Man hat Operator-Overloading in Java ja nicht deshalb nicht eingebaut, weil man es nicht könnte, sondern weil man es für schlecht hält. Man hat gesehen, dass dieses Feature bei geringem Nutzen oft mißbraucht wird und hat es deshalb lieber nicht in die Sprache integriert.



  • Dann ist man in Java aber ganz schön inkonsequent:

    Java Code:

    String str = "Hallo" + "Du da!";
    

    :p



  • @artchi - ja aber strings sind sowieso ganz "eigene" objekte in java 😉

    C# hat schon nette features und MS hat da schon eine ganz passable sprache zusammengebaut
    also ich persoenlich mag die sprache sehr - und dabei bin ich ja als java mensch bekannt

    ms hat hier ne taktik angewandt die sie schon immer machten: sie erkennen potential einer sprache, steigen in dem gebiet rapide ein wobei sie teilbereiche einfach kopieren und den rest verbessern sie soweit als das sie demit den markt beherschen koennen - ob das jetzt beim fall c# gegen java als prädominierende sprache wirklich passieren wird ist ne andere frage, aber ich glaube sie haben schon zu lange gewartet

    im endeffekt bietet C# viele java features und einige eigenheiten, dazu kommt noch der .NET unterbau der sehr wohldurchdacht ist



  • über operatorenüberladung kann man schon streiten. aber ich finde

    if (obj1.compareTo(obj2) < 0) ...
    schlechter als
    if (obj1 < obj2)
    

    aber is das nicht in java 1.5 dabei?



  • Das ist ja auch nicht äquivalent. Mit compareTo kannst du auch die Fälle trennen, wo die Objekte gleich sind und wo obj1 > obj 2. Das kannst du mit dem "<" nicht. Du bräuchtest da also einen Operator mit einer dreiwertigen Logik, den es natürlich nicht gibt.



  • Gregor schrieb:

    1. Ja, momentan kann man neben Java nur 189 andere Sprachen nutzen, um Java-Bytecode zu erzeugen: Programming Languages for the Java Virtual Machine

    Und wer macht das?



  • Man hat Operator-Overloading in Java ja nicht deshalb nicht eingebaut, weil man es nicht könnte, sondern weil man es für schlecht hält.

    Stellt sich die Frage, wer genau "Man" ist und warum "Man" es für schlecht hält? James Gosling zumindest hat bereits im Jahr 2000 gesagt, dass das Fehlen von Operatorüberladung in Java seine Nachteile hat. So ist Java ohne Operatorüberladung z.B. für "Numerics"-Leute völlig uninteressant. Eine Sache die Gosling nicht so wirklich schmeckt.

    Gregor schrieb:

    MaSTaH schrieb:

    Das nennst du syntaktischen Zucker der nur Zeichen spart? Sowas kann doch nur von einem eingefleischten Javaiianer kommen 😉 .

    Naja, natürlich ist das meine persönliche Sichtweise. Ich halte ein

    c = a + b;
    

    statt einem

    c = a.add(b);
    

    für eine sehr geringe Veränderung. Das ändert nicht die Art, wie man programmiert, sondern erspart einem nur ein paar Zeichen.

    Es bleibt in der Regel wohl kaum bei a + b. Was ist zum Beispiel hiermit (ist C++):

    Z = add( add( R, mul( mul( j, omega ), L ) ),
    div( 1, mul( j, omega ), C ) ) );
    

    vs:

    Z = R + j*omega*L + 1/(j*omega*C);
    

    Wie schnell hast du erkannt, dass die erste Formel nicht korrekt ist? Und wie schnell hast du die Formel in der ersten Version überhaupt wiedererkannt?

    Operator-Überladung ist ein weiteres Abstraktionsmittel einer Sprache. Es hilft dabei neue Datentypen zu entwickeln, die eingebauten syntaktisch in nichts nachstehen. Diese Form der Transparenz ist manchmal doch durchaus erwünscht. Bibliotheken wie die Iostream-Lib von C++ zeigen eine weitere sinnvolle Anwendung von Operatorüberladung (Erweiterung eines syntaktischen Frameworks).

    Natürlich kann man mit OÜ auch viel unsinn betreiben, aber das gilt eigentlich für alle machtvollen Abstraktionsmittel.

    Letztlich ist OÜ imo entweder das fehlende Salz oder aber das ärgerliche Haar in der Suppe. Da wo man es braucht, braucht man es wirklich und wenn es fehlt, muss man hässliche Workarounds verwenden. Bricht man hingegen einmal die Regeln oder implementiert man einen Operator so neu, dass dessen Semantik nicht jedem wirklich klar ist, dann hat man mehr Ärger als Nutzen.



  • Gregor@UNI schrieb:

    Das ist ja auch nicht äquivalent. Mit compareTo kannst du auch die Fälle trennen, wo die Objekte gleich sind und wo obj1 > obj 2. Das kannst du mit dem "<" nicht. Du bräuchtest da also einen Operator mit einer dreiwertigen Logik, den es natürlich nicht gibt.

    hm. du meinst wohl sowas:

    int ret = obj1.compareTo(obj2);
    if (ret > 0) // bla
    else if (ret < 0) // blubb
    else // tralla
    

    hm, schön. ich glaub ich hab dich falsch verstanden :p ich jedenfalls verwende den vergleichsoperator immer spezifiziert:

    if (obj1 < obj2) // blubb
    else if (obj1 < obj) // trulla
    else // tralla
    

    oder was hab ich da jetz falsch verstanden? vielleicht dass man nicht 3 operatoren explizit deklarieren muss, sondern alle drein implementierungen in eine klatscht? wie gesagt, geschmackssache 🙂 ich hoff, java 1.5 kanns, weil ich java demnächst für ein größeres projekt hernehmen will

    edit: dito hume, schön argumentiert 🙂



  • btw. arbeitet glaube ich das dotGNU Projekt daran, einen dotNET-Assemblie-to-Java-ByteCode Compiler zu schreiben...



  • HumeSikkins schrieb:

    Natürlich kann man mit OÜ auch viel unsinn betreiben, aber das gilt eigentlich für alle machtvollen Abstraktionsmittel.

    Genau das habe ich nie verstanden. Inwiefern kann ich mit Operaoren Ueberladung mehr Bloedsinn machen als ich mit Funktionen/Methoden kann.

    Ich kann zwar den op+ zum dividieren verwenden, aber ich kann genauso eine Funktion
    writeToFile()
    lediglich einen Wert ausrechnen lassen.

    Kannst du mir das bitte erklaeren wie ich mit OUe unlesbarere Programme schreiben kann als mit bloeden Funktionsnamen?

    btw:
    c=a.add(b);
    wieso gehoert das add zu a? und warum nicht zu b?
    Was wenn das 2 verschiedene Typen sind? Es hat ja seinen Grund warum man den operator+ nicht als (non static) Member definiert 😉

    und ein
    Foo a;
    Bar b;
    c=Foo.add(a,b)
    ist ja auch komisch. Wieso gehoert das add denn zu Foo und nicht zu Bar??

    mich verwirrt sowas immer 😞



  • Shade Of Mine schrieb:

    btw:
    c=a.add(b);
    wieso gehoert das add zu a? und warum nicht zu b?

    Weil a der linksseitige Operand ist.

    Shade Of Mine schrieb:

    Was wenn das 2 verschiedene Typen sind?

    Was soll dann sein?



  • Sgt. Nukem schrieb:

    Shade Of Mine schrieb:

    btw:
    c=a.add(b);
    wieso gehoert das add zu a? und warum nicht zu b?

    Weil a der linksseitige Operand ist.

    Shade Of Mine schrieb:

    Was wenn das 2 verschiedene Typen sind?

    Was soll dann sein?

    Dann muss ich die Funktion 2 mal implementieren.
    einmal in Foo fuer Bar und einmal in Bar fuer Foo

    finde ich persoenlich ungut.
    vorallem wenn ein
    a.add(b) geht, aber ein b.add(a) nicht.

    weiters hat man ein namenproblem:
    ist add jetzt der op+ oder der op+=?



  • das ganze nähert sich der gretchenfrage :p
    ich fänds einfach schön, wenn java op-overloading hätte, dann würd ichs öfter einsetzen glaub ich.



  • @Shade
    Funktionen beinhalten an sich erstmal überhaupt keine Semantik. Sie haben ja erstmal keinen Namen. Diesen musst du erst explizit erfinden. Operatoren hingegen werden nicht explizit benannt. Sie haben ihren Namen (bzw. ihr Symbol) von Anfang an. Genauso wie eine (erwartete) Semantik.
    Das sind imo also zwei unterschiedliche Herangehensweisen. Auf der einen Seite entwickelst du ein bestimmtes Verhalten und gibst diesem danach explizit einen Namen (->Funktion). Auf der anderen Seite hast du einen Namen gegeben und entwickelst darein ein bestimmtes Verhalten (->Operator).

    Das Problem bei Operatoren ist die Geschichte mit der Semantik. Wenn die nicht allen 100% klar ist (wenn sich also nicht alle einig sind, was ein Operator genau bedeutet), spielst du ein Spiel mit der Intuation des Anwenders.
    Ein Beispiel (angelehnt an Dewhursts: "C++ Gotchas")

    template <class T, int size>
    class Array
    {
    public:
        ...
        Array& operator=(const T& val);
    };
    

    Hat der =-Operator hier wirklich nur eine Bedeutung die allen klar ist?

    Array<int, 50> arr;
    arr = 75;
    

    Für dich bedeutet diese Anweisung logischerweise, dass alle 50 Elemente von arr mit 75 belegt werden. Ein Anderer könnte aber denken, dass hier das Array auf 75 Elemente vergrößert wird. Und wieder andere finden, dass hier das erste Element mit 75 belegt wird.
    Drei mögliche Interpretationen für das selbe Zeichen -> nicht gut. Da mit einem Operator aber immer auch Intuition verbunden ist (die kennen wir schließlich schon aus der Schule), wird wahrscheinlich jeder denken, dass seine Intuition die Richtige ist.

    Inwiefern unterscheidet sich das jetzt von einer völlig falsch benannten Funktion:

    template <class T, int size>
    class Array
    {
    public:
        ...
        Array& assign(const T&); // schrecklicher Name. Besser wäre sowas wie setAll
    };
    
    Array<int, 50> arr;
    arr.assign(75);
    

    Meiner Meinung nach in einer eher technischen und einer eher emotionalen Hinsicht:
    arr.assign() ist direkt als Methodenaufruf zu identifizieren. Damit sehe ich sofort, in welchem Kontext ich nach einer Dokumentation suchen muss (die Syntax garantiert mir, dass hier keine unsichtbaren Konvertierungen auf dem linken Operand stattfinden können). Bei einem Operator hingegen wird das schneller mal verschleiert. Hinzukommend ist die Wahrscheinlichkeit, dass jemand in die Doku schaut bei einer Funktion deutlich höher, da man sich zum bei einer Funktion a) nicht so sehr auf seine Intuition verlässt (drei Funktionen die das gleiche machen, haben in drei Frameworks drei leicht verschiedene Namen. Man hat sich also nicht so sehr an einen Namen gewöhnt) und b) ist man es gewöhnt, dass die Semantik einer Funktion in einer API-Dokumentation genauer beschrieben wird.

    Letztlich ist die Frage aber nicht, ob schlechte Operatorüberladung schlimmer ist als falsch benannte Funktionen. Vielmehr geht es ja darum, dass Operatorüberladung dazu verleiten kann, dass du eine Funktionalität die ungefähr so ähnlich ist wie zuweisen in ein operator=-Korsett presst.
    Das kann dir mit Funktionen nicht so schnell passieren, da du hier ja *explizit* einen Namen vergeben musst. Und wenn du sowieso weißt, dass du "allen Elementen einen Wert X zuweisen" implementiert hast, dann kannst du deine Funktion auch *genau* passend benennen.
    Es gibt dummerweise aber nun mal keinen Operator "allen Elementen einen Wert X zuweisen".



  • Zusatz: Natürlich könnte man jetzt auch einfach sagen, dass der Nutzer einfach die Bedeutung des Operators in der Doku nachschlagen soll (nach dem Motto: Wer eine Funktion nachschlagen kann, der kann auch einen Operator nachschlagen). Das ist aber gerade nicht im Sinne des Erfinders und zerstört den wirklichen Vorteil von Operatorüberladung.
    Das ich statt 8 Zeichen nur eines eingeben muss, ist ja nicht wirklich relevant. Es geht ja gerade darum, dass ich es einem Anwender ermögliche, dass er sein ohnehin vorhandene Wissen intuitiv anwenden kann. Er will die komplexen Zahlen x und y addieren, schreibt x + y und muss nicht erst in der Doku nachschauen ob die Funktion nun add, Add oder gar addieren heißt.
    Muss die Semantik einer Operatorimplementierung erst nachgeschlagen werden, dann ist das imo ein unschlagbares Zeichen dafür, dass ich lieber keinen Operator überladen hätte.


Log in to reply