Klasse: "Pass by Reference" falsch?



  • GPC schrieb:

    Es stiefelt ja auch keiner durch die Gegend und sagt int x; wäre die Definition und nicht die Deklaration von x.

    "int x;" ist sowohl Deklaration als auch eine Definition. Deklarieren darfst du sooft zu willst, wenn du zweimal "int x;" im selben Block schreibst beschwert sich der Compiler. In C# ist Deklaration aber praktisch immer auch gleich Definition und andersrum.
    Aber das gehört nicht hierher.

    Bashar schrieb:

    Nochmal ein Beispiel:

    Derived obj = new Derived();
    Base b = obj;
    

    Wie willst du sowas verstehen, wenn für dich obj das Objekt ist? Was ist dann b? Eigentlich auch obj ... aber hat obj jetzt einen anderen Typ? Nope, das Objekt "schwebt" im Hintergrund, und die beiden Variablen sind unterschiedliche Sichten darauf. Oder halt Referenzen.

    Es ist für jeden deutlich verständlicher, wenn man davon spricht, dass eine Referenz auf das Objekt hier übergeben wird

    Korrekt.

    und wir somit ein Call-By-Reference haben.

    Das folgt daraus nicht. Und es ist IMO irreführend. Schon allein, weil du dann nicht weißt, wie du die Übergabe mithilfe von ref nennen sollst. Aber auch ohne das, die gleiche Diskussion gibts schließlich auch in Java.

    Und ich finde es verwirrend es nicht "by reference" zu nennen wenn doch eine Referenz übergeben wird. Das dann als "by value" zu bezeichnen passt nicht.

    Die Übergabe mittels ref ist dann die Übergabe der Referenz by Referenze, was denn sonst ?



  • DarkShadow44 schrieb:

    Die Übergabe mittels ref ist dann die Übergabe der Referenz by Referenze, was denn sonst ?

    Du widersprichst dir damit selbst, denn nach der Logik müsste die Übergabe ohne ref "Übergabe der Referenz by Value" heißen.



  • DarkShadow44 schrieb:

    Deklarieren darfst du sooft zu willst, wenn du zweimal "int x;" im selben Block schreibst beschwert sich der Compiler.

    Du meinst sicher, dass ich so oft definieren darf, wie ich will. Vielleicht liest du noch mal genau nach, was der Unterschied zwischen Deklaration und Definition ist 😉

    DarkShadow44 schrieb:

    Und ich finde es verwirrend es nicht "by reference" zu nennen wenn doch eine Referenz übergeben wird. Das dann als "by value" zu bezeichnen passt nicht.

    Die Übergabe mittels ref ist dann die Übergabe der Referenz by Referenze, was denn sonst ?

    Ich finde, diese beiden Aussagen schließen sich gegenseitig aus.



  • GPC schrieb:

    Du meinst sicher, dass ich so oft definieren darf, wie ich will. Vielleicht liest du noch mal genau nach, was der Unterschied zwischen Deklaration und Definition ist 😉

    <a href= schrieb:

    http://www.c-plusplus.net/forum/61231-full pumuckl">

    class foo;          // <-- Deklaration von foo 
      
    class foo {         // <-- Definition  von foo 
     /*...*/
    }; 
        
    extern int yay;     // <-- Deklaration von yay 
    int yay;            // <-- Definition  von yay
    

    Wo liegt jetzt mein Fehler ? 😕

    Bashar schrieb:

    DarkShadow44 schrieb:

    Die Übergabe mittels ref ist dann die Übergabe der Referenz by Referenze, was denn sonst ?

    Du widersprichst dir damit selbst, denn nach der Logik müsste die Übergabe ohne ref "Übergabe der Referenz by Value" heißen.

    Naja letztlich wird bei einer Übergabe immer etwas kopiert, und sei es nur die Referenz. Ja, insofern müsste es ohne ref "Übergabe der Referenz by Value" und mit ref "Übergabe der Referenz by Referenze by Value" heißen. Da würde ich jeweils das letzte "by value" allerdings weglassen, da klar ist dass die Referenz kopiert werden muss, die Methode muss schließlich irgendwas erhalten.



  • Ich hab irgendwie das Gefühl, du hast gar keine Meinung zu dem Thema und reimst dir von Post zu Post irgendwas zusammen. Auch gut, du wirst wohl irgendwann bei der etablierten Bezeichnung ankommen 😉



  • Bashar schrieb:

    Ich hab irgendwie das Gefühl, du hast gar keine Meinung zu dem Thema und reimst dir von Post zu Post irgendwas zusammen. Auch gut, du wirst wohl irgendwann bei der etablierten Bezeichnung ankommen 😉

    Und ich glaube du versuchst es nicht zu verstehen.
    Nochmal als einfachere Fassung:
    By value heißt dass das objekt kopiert wird. By Reference heißt dass es nicht kopiert wird. Ergo:

    void method(Class1 obj) // by reference (auch wenn die referenz auf runtime level sicher by value übergeben wird)
    


  • DarkShadow44 schrieb:

    Und ich glaube du versuchst es nicht zu verstehen.
    Nochmal als einfachere Fassung:

    Einfacher heißt in dem Fall, dass du den größeren Blödsinn ("reference by value") weglässt? Dazu hätte ich ja auch noch was zu sagen gehabt 😉

    By value heißt dass das objekt kopiert wird.

    Nein, das Argument wird kopiert.

    By Reference heißt dass es nicht kopiert wird.

    Nein. Es heißt, dass das Argument als (implizite) Referenz übergeben wird.

    Ergo:

    void method(Class1 obj) // by reference (auch wenn die referenz auf runtime level sicher by value übergeben wird)
    

    Es geht nicht um die Runtime, sondern um die Semantik.



  • Dravere schrieb:

    Ich kann mich nur wiederholen. Unterscheidet zwischen Sprach- und Runtime-Level.
    (...)

    Ich glaub es geht wirklich darum was Dravere schreibt.

    Also uns wurde früher in C++ eben so beigebracht, dass:

    int *i = new int();
    foo(*i) //by value
    foo(i) //by referenz
    

    Dabei ist mir sehr wohl bewusst, dass der Parameter by value übergeben wird.
    Folgendes funktioniert also natürlich nicht:

    void foo(int *i) 
    {i = nullptr;}
    


  • Dazu hab ich doch auch schon was gesagt. Die Übergabe eines Pointers kann Call-by-reference simulieren, aber es ist weiterhin Call-by-value.

    Bei C++-Referenzen kann man sich streiten -- IMHO gehört zum Konzept von Call-by-reference, dass sich das nur auf Parameter bezieht, C++ hat Referenzen jedoch als normalen Datentyp. Nun sind C++-Referenzen keine Objekttypen, können also nicht kopiert werden. Kann man also davon sprechen, dass da eine Referenz by-value übergeben wird, eher nicht. Wird das Argument also by-reference übergeben? Eigentlich schon, aber diese Art der Argumentübergabe unterscheidet sich genaugenommen in nichts von jeder anderen Argumentübergabe, da dort i.A. nicht kopiert wird, sondern Formalparameter mit Aktualarametern in dergleichen Weise wie sonst auch initialisiert werden. Daher tendiere ich zu der Meinung, dass das Konzept von Call-by-reference im Grunde genommen überholt ist und insbesondere in C++ sinnlos geworden ist. Bei Sprachen wie C# passt es jedoch noch. Das ist ja dasselbe wie z.B. in Pascal mit seinen var-Parametern.
    </imho>



  • Ich kann die Argumentation ebenfalls nicht nachvollziehen, dass eine einfache Parameterübergabe in C# Call-by-Reference ist. Es ist Call-by-Value und nichts anderes. Wenn man das verschleiert ist weder angeblich verwirrten Anfängern geholfen, noch kann ich im Gespräch den Unterschied zu echtem Call-By-Reference mittels ref-Modifier ausdrücken.

    Es ist gerade für Anfänger wichtig das irgendwann zu begreifen. Man sieht hier im C# Forum oft wilde Konstrukte aus denen ganz klar hervorgeht, dass der Schreiber nicht verstanden hat, wie es um die Lebenszeit von Objekten, Referenz- und Wertetypen gestellt ist. Bashar hat es schon richtig gesagt, da muss man irgendwann durch und es ist nun wirklich nicht so schwierig zu verstehen.



  • DarkShadow44 schrieb:

    Wo liegt jetzt mein Fehler ? 😕

    In dem verlinkten Beispiel ist alles korrekt. Was ich meinte:

    public void foo() {
      int x; //<- Deklaration
      x = 5; //<- Definition
      x = 4; //<- Erneute Definition, klappt logischerweise
      int x; //<- Zweite Deklaration, würde nicht klappen - ist klar
    
      int y = 10;  //<- Deklaration + Definition in einem
    }
    

    Ich denke, damit können wir das Thema auch ruhen lassen 😉 Wahrscheinlich haben wir in dem Punkt nur aneinander vorbeigequatscht, weil du eher Klassen-/Funktionsdeklarationen im Sinn hattest.

    By value heißt dass das objekt kopiert wird.

    Ich würde dir hier auch dringend empfehlen, mal von "das Objekt"-Sichtweise wegzukommen und einfach festzustellen.. es wird ein Argument übergeben. Das Argument ist nicht das Objekt selbst, wenn es sich um Referenztypen handelt. Vielleicht fällt es dann leichter, dass offensichtliche und faktisch korrekte (= call by value) zu akzeptieren 😉



  • Das Argument ist nicht das Objekt selbst, wenn es sich um Referenztypen handelt. Vielleicht fällt es dann leichter, dass offensichtliche und faktisch korrekte (= call by value) zu akzeptieren

    Und genau da sind wir wieder bei der Unterscheidund zwischen Sprach- und Runtime-Level 😃
    Faktisch ist es korrekt dass das Argument by-value übergeben wird, ja.

    Aber:
    Wenn ich einer Methode ein Objekt übergebe, übergebe ich (semantisch) das Objekt einer Klasse, und nicht ein Handle!
    Insofern ist für mich das Objekt das Argument das übergeben wird, und nach dieser Sichtweise ist meine Übergabe definitv "by reference".

    Darum auch der Vorschlag der Unterscheidung in Runtime - und Sprachlevel.
    Auf Runtimelevel hast du recht, da wird nur ein Handle by-value übergeben.
    Auf Sprachlevel übergebe ich allerdings ein Objekt einer Klasse, daher ist die Übergabe by reference.

    Es ist gerade für Anfänger wichtig das irgendwann zu begreifen. Man sieht hier im C# Forum oft wilde Konstrukte aus denen ganz klar hervorgeht, dass der Schreiber nicht verstanden hat, wie es um die Lebenszeit von Objekten, Referenz- und Wertetypen gestellt ist. Bashar hat es schon richtig gesagt, da muss man irgendwann durch und es ist nun wirklich nicht so schwierig zu verstehen.

    Ich würde jetzt nicht sagen dass das was mit Anfängern oder fehlendem Verständnis zu tun hat. Wir verstehen ja hier alle wie die Übergabe in C# läuft, wir hängen uns hier nur an Definitionen auf. 😃
    Und wenn ich eine struct übergebe und das als "by value" bezeichne, werde ich die Übergabe einer class nicht auch als "by value" bezeichnen, weil es nunmal was komplett anderes macht. Auch wenn im Hintergrund nur ein Handle by-value übergeben wird bezeichne ich die Übergabe als Übergabe einer Referenz.



  • DarkShadow44 schrieb:

    Wir verstehen ja hier alle wie die Übergabe in C# läuft, wir hängen uns hier nur an Definitionen auf. 😃

    Und Microsoft definiert, wie es in C# genannt wird.



  • DarkShadow44 schrieb:

    Auf Runtimelevel hast du recht, da wird nur ein Handle by-value übergeben.
    Auf Sprachlevel übergebe ich allerdings ein Objekt einer Klasse, daher ist die Übergabe by reference.

    Was du Runtime nennst, ist in Wirklichkeit das Sprachlevel. Und was du semantisch nennst, ist deine subjektive Vorstellung.


  • Administrator

    GPC schrieb:

    Ich würde dir hier auch dringend empfehlen, mal von "das Objekt"-Sichtweise wegzukommen und einfach festzustellen.. es wird ein Argument übergeben. Das Argument ist nicht das Objekt selbst, wenn es sich um Referenztypen handelt. Vielleicht fällt es dann leichter, dass offensichtliche und faktisch korrekte (= call by value) zu akzeptieren 😉

    Nein. Mir zumindest nicht. Weil dieses "andere" als das "Objekt" in C# völlig transparent ist und daher eigentlich nicht vorhanden. Ihr führt einfach eine unnötige zusätzliche Definition ein, wodurch es einfach nur komplizierter wird zu verstehen und einem überhaupt nichts bringt.

    Ich finde es so schön, auf der deutschen Wikipedia steht das folgende zum "Spezialfall" Java:
    http://de.wikipedia.org/wiki/Referenzparameter

    Wikipedia DE schrieb:

    In der Sprache Java wird bei primitiven Datentypen automatisch ein Wertparameter verwendet. Bei Objekten wird die Objektreferenz als Wertparameter durch Kopie übergeben. Die aufgerufene Methode kann also den Zustand des referenzierten Objekts verändern, jedoch nicht die ursprüngliche Referenz selbst – sie zeigt also nach der Rückkehr aus dem Methodenaufruf auf dasselbe Objekt wie zuvor. Die Terminologie vieler Java-Publikationen verdeckt diesen Umstand. [1]

    1. Möchte ich hier mal hervorheben, wie interessanterweise sehr viele Java-Publikationen diesen Umstand verdecken. Was mir bisher bei C# ebenfalls aufgefallen ist. Man mag sich hier mal fragen wieso? Aber wahrscheinlich sind das alles Idioten, welche nicht verstehen wie Java/C# funktioniert?
    2. Wenn man dieser Referenz folgt, dann kommt man hierher:
    http://javadude.com/articles/passbyvalue.htm
    Daraus möchte ich das folgende zitieren:

    I'm a compiler guy at heart. The terms "pass-by-value" semantics and "pass-by-reference" semantics have very precise definitions, and they're often horribly abused when folks talk about Java. I want to correct that...

    Und genau da sehe ich das Problem. Der Typ sieht das Ganze aus der Kompilerwelt. Interessanterweise hat er anscheinend auch einen C oder C++ Hintergrund, wie wohl viele von euch auch. Wieso darf es nicht unterschiedliche Definitionen auf unterschiedlichen Ebenen geben? Ja, im Bereich der Runtime/Kompiler ist es ein Call-By-Value aber auf dem abstrakten Sprach-Level ein Call-By-Referenz.

    Ich habe Mühe hier weiter zu argumentieren, da es mir vorkommt, als ob ich jemandem erklären müsste, wieso 2 + 2 gleich 4 ist. Es ist mir völlig rätselhaft, wieso man hier sich so dermassen stur stellen will und unbedingt an irgendwelchen Definitionen festhalten möchte, auch wenn sie überhaupt keinen Mehrwert geben. Das ist Erbsenzählerei, welche niemandem was bringt.

    Könnte mir jemand sagen, wieso es relevant ist, diese Abstrahierung einem C# Programmierer sichtbar zu machen? Vielleicht können wir darüber einen Weg finden? Wieso muss ein C# Programmierer wissen, dass hier tatsächlich das Argument kopiert wird? Ich sehe einfach nicht, was die Vorteile sind, diese Abstraktion wieder sichtbar zu machen. Und bitte keine Argumente à la: "Weil es halt korrekt ist!"

    µ schrieb:

    Es ist gerade für Anfänger wichtig das irgendwann zu begreifen. Man sieht hier im C# Forum oft wilde Konstrukte aus denen ganz klar hervorgeht, dass der Schreiber nicht verstanden hat, wie es um die Lebenszeit von Objekten, Referenz- und Wertetypen gestellt ist. Bashar hat es schon richtig gesagt, da muss man irgendwann durch und es ist nun wirklich nicht so schwierig zu verstehen.

    Das hat doch überhaupt nichts damit zu tun! Im Gegenteil, du verwirrst ihn eben eher noch mehr, wenn du diese seltsame Definition durchziehst. Du kannst es ihm deutlich einfacher erklären, wenn du nicht alles als Call-By-Value definierst.

    Oder vielleicht noch ein anderer Ansatz:
    Vielleicht ist allgemein der Begriff Call-By-Value und Call-By-Reference nicht eindeutig genug? Ich meine eine solche Diskussion wie hier gibt es nicht zum ersten Mal. Man gehe nur in entsprechende Foren suchen. Die Diskussionen wurden schon sehr sehr oft geführt und das zeigt doch, dass die Definitionen einfach schlecht sind, sonst müsste man nicht so oft darüber diskutieren.

    Grüssli



  • Dravere schrieb:

    Ich finde es so schön, auf der deutschen Wikipedia steht das folgende zum "Spezialfall" Java:
    http://de.wikipedia.org/wiki/Referenzparameter

    2. Wenn man dieser Referenz folgt, dann kommt man hierher:
    http://javadude.com/articles/passbyvalue.htm

    Ich habe Mühe hier weiter zu argumentieren, da es mir vorkommt, als ob ich jemandem erklären müsste, wieso 2 + 2 gleich 4 ist.

    http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing



  • Dravere schrieb:

    GPC schrieb:

    Ich würde dir hier auch dringend empfehlen, mal von "das Objekt"-Sichtweise wegzukommen und einfach festzustellen.. es wird ein Argument übergeben. Das Argument ist nicht das Objekt selbst, wenn es sich um Referenztypen handelt. Vielleicht fällt es dann leichter, dass offensichtliche und faktisch korrekte (= call by value) zu akzeptieren 😉

    Nein. Mir zumindest nicht. Weil dieses "andere" als das "Objekt" in C# völlig transparent ist und daher eigentlich nicht vorhanden. Ihr führt einfach eine unnötige zusätzliche Definition ein, wodurch es einfach nur komplizierter wird zu verstehen und einem überhaupt nichts bringt.

    Ich finde nicht, dass ich bzw. wir eine zusätzlich Definiton einführen, denn dass bei void Foo(Object o) eine Referenz kopiert wird, kann man wohl schlecht leugnen 😉 Die Dinge werden eben so benannt, wie sie auch sind.
    Es gibt hier aus meiner Sicht auch keinen Unterschied zwischen "Sprachlevel" und "Compilerlevel".. das ist alles das gleiche, denn überall passiert das gleiche und nichts wird verschleiert.. es passiert nirgends iwelche Compiler-Magic wie z.B. beim dynamic-Schlüsselwort.

    Wikipedia DE schrieb:

    In der Sprache Java wird bei primitiven Datentypen automatisch ein Wertparameter verwendet. Bei Objekten wird die Objektreferenz als Wertparameter durch Kopie übergeben. Die aufgerufene Methode kann also den Zustand des referenzierten Objekts verändern, jedoch nicht die ursprüngliche Referenz selbst – sie zeigt also nach der Rückkehr aus dem Methodenaufruf auf dasselbe Objekt wie zuvor. Die Terminologie vieler Java-Publikationen verdeckt diesen Umstand. [1]

    1. Möchte ich hier mal hervorheben, wie interessanterweise sehr viele Java-Publikationen diesen Umstand verdecken. Was mir bisher bei C# ebenfalls aufgefallen ist. Man mag sich hier mal fragen wieso? Aber wahrscheinlich sind das alles Idioten, welche nicht verstehen wie Java/C# funktioniert?

    Ich halte dich nicht für einen Idioten (obwohl du etwas gelassener sein könntest ;)). Ich denke sogar, du bist der besserer Programmierer als ich und ich weiß auch, dass du absolut weißt, was bei Referenztypen als Parametern tatsächlich passiert usw.
    Ansonsten deckt der Wikipedia-Eintrag eigentlich nur meine Sichtweise, aber er vermeidet halt, es call by value zu nennen.

    Ich habe Mühe hier weiter zu argumentieren, da es mir vorkommt, als ob ich jemandem erklären müsste, wieso 2 + 2 gleich 4 ist.

    Komisch, so geht's mir auch 🤡 Kurioser wird es nur noch dadurch, dass die Fakten für mich gar keine andere Sichtweise als meine zulassen.

    Könnte mir jemand sagen, wieso es relevant ist, diese Abstrahierung einem C# Programmierer sichtbar zu machen? Vielleicht können wir darüber einen Weg finden? Wieso muss ein C# Programmierer wissen, dass hier tatsächlich das Argument kopiert wird? Ich sehe einfach nicht, was die Vorteile sind, diese Abstraktion wieder sichtbar zu machen. Und bitte keine Argumente à la: "Weil es halt korrekt ist!"

    Erstens: Weil es halt korrekt ist 😃 Wir sind Informatiker, wir entwickeln komplexe Software und präzise Aussagen sind wichtig und auch notwendig. Es macht keinen Sinn, etwas anders zu benennen, als es ist.
    Zweitens: Ich kam aus der C++ Welt nach C# und am Anfang musste ich mich erstmal reindenken, wie das jetzt eig. mit Referenztypen als "nicht-ref"-Parameter ist. Ich finde nach wie vor das C++ Modell viel einfacher, btw.
    Drittens: Meine Sichtweise hilft beim Verständnis, warum folgender Code eben das macht, was er macht:

    public void Foo(Object o) {
      o = null;
    }
    
    public void Bar(ref Object o) {
      o = null;
    }
    
    void Main () {
      Object o = "Wazuuuuup";
      Foo(o);
      Console.Write(o == null);  //false!
    
      Bar(ref o);
      Console.Write(o == null);  //true!
    }
    

    Und wenn laut deiner Meinung Foo schon call by reference ist, dann ist Bar dann "ultra call by reference"? 😉

    Ich weiß, ich werde dich nicht überzeugen. Du genausowenig mich. Zudem sind wir hier im Internet, hier hat noch nie jemand einen anderen von seiner Meinung überzeugt, also können wir es auch gut sein lassen 😉


  • Administrator

    Ok. Ich war gestern recht müde und erst recht heute Morgen um 2 Uhr. Ich habe es mir nun nochmals alles in Ruhe durch den Kopf gehen lassen. Ich schlage nun einfach eine neue Art von Bennennung vor. Ähnlich wie das von volkard verlinkte Call-By-Sharing nur hoffentlich exakter. Und darin werde ich hoffentlich auch rüber bringen können, wieso ich das Call-By-Value und Call-By-Reference hier als störende Erwähnung empfinde, welche keinen Nutzen bringt.

    Zuerst aber noch ein zwei andere Dinge bezüglich GPCs Antwort:

    GPC schrieb:

    Die Dinge werden eben so benannt, wie sie auch sind.

    Hier frage ich mich eben, ob es Sinn macht, sie auch so zu nennen, oder ob eine andere Nennung nicht viel verständlicher wäre. Ich will mich nicht fix an eine Definition halten, nur weil sie richtig ist. Mir ist es auch wichtig, dass sie leicht verständlich ist.

    GPC schrieb:

    obwohl du etwas gelassener sein könntest 😉

    Das wäre definitiv von Vorteil.

    Nun zu meinem Vorschlag:
    - Call-With-Object-Copy
    - Call-With-Object-Reference
    - Call-With-Variable-Reference

    struct MyStruct { }
    
    var s = new MyStruct();
    
    void Foo(MyStruct s) { }
    
    Foo(s);
    

    Was ist hier wichtig? Meiner Meinung nach ist hier wichtig, dass man zu verstehen gibt, dass das Objekt selber kopiert wird. Änderungen an s in der Funktion Foo bleiben in der Funktion. Call-By-Value sagt das grundsätzlich auch aus, aber ein Call-With-Object-Copy womöglich deutlicher. Aber hier hatten wir ja noch kein Konflikt, beim nächsten Beispiel wird es vielleicht interessanter und ihr seht vielleicht mein 2 + 2 = 4 Problem.

    class MyClass { }
    
    var c = new MyClass();
    
    void Foo(MyClass c) { }
    
    Foo(c);
    

    Was ist hier wichtig? Wichtig ist zu sehen, dass die Funktion Foo mit einer Referenz zum Objekt aufgerufen wird. Änderungen in der Funktion Foo über die Variable c am Objekt propagieren nach draussen. Der Begriff Call-By-Value führt hier eine unnötige gleiche Bezeichnung zum ersten Fall ein. Der Begriff verschleiert etwas entscheidendes nur weil man ihn an einem Implementierungsdetail festnagelt, welches überhaupt nicht relevant ist. Daher hier mein Vorschlag, dass man dies als Call-With-Object-Reference nennt. Denn genau das ist und wir bekommen eine saubere Unterscheidung zum vorherigen Fall ohne auf Implementierungsdetails einzugehen. Und das ist meiner Meinung nach äusserst wichtig.

    var v = new MyClass();
    
    void Foo(ref MyClass v) { }
    
    Foo(ref v);
    

    Was ist hier wichtig? Wichtig ist, dass eine Referenz auf die Variable v und nicht auf das Objekt übergeben wird. Daher ist mein Vorschlag hier, dies Call-With-Variable-Reference zu nennen.

    Es erscheint mir etwas seltsam, dass man ein Implementierungsdetail in der Erklärung der Sprache selbst verwendet. Was macht ihr, wenn sich die Implementierung nun auf einmal ändern würde und man dies anders löst? Die Sprache C# sieht immer noch genau gleich aus, das Verhalten ist immer noch genau gleich und nur die Implementierung ändert. Dass man dann plötzlich diese Begriffe anpasst, macht auf mich einfach keinen Sinn. Hier braucht es einfach eine Abstraktionsebene in der Erklärung über den Implementierungsdetails.

    Grüssli



  • Dravere schrieb:

    Weil dieses "andere" als das "Objekt" in C# völlig transparent ist und daher eigentlich nicht vorhanden.

    Ist es nicht. Im übrigen ist deine Position sogar noch radikaler als die von DarkShadow. Er weiß, dass Objektvariablen Referenzen sind, er hat aber Bauchschmerzen dabei, das Call-by-value zu nennen, weil es sich ein bisschen wie Call-by-reference anfühlt, was durchaus nachvollziehbar ist. Du dagegen leugnest, dass die Referenznatur einer Objektvariable irgendeine semantische Relevanz hat. Könntest du das mal versuchen, plausibel zu begründen?

    Ich finde es so schön, auf der deutschen Wikipedia steht das folgende zum "Spezialfall" Java:

    Ich weiß nicht, was an Java ein Spezialfall sein soll. Da gibts ständig dieselbe Diskussion wie hier, aber Java hat das nicht erfunden. Viele Sprachen funktionieren so, dass gewisse primitive Typen herumkopiert werden und komplexere Typen durch Referenzen dargestellt werden, Common Lisp zum Beispiel. Aber ich hab noch nie gelesen, dass irgendwer das für Call-by-reference hält oder Probleme mit sowas hat:

    (defun foo (arg)
      (setf arg '(hallo welt)))  ; nicht beim Aufrufer sichtbar
    

    Insofern ist Java vielleicht wirklich ein Spezialfall 😉
    edit: Sorry, das Lisp-Beispiel passt nicht ganz, weil die Sprechweise in Lisp anders ist. Da Guy Steele an Java mitgearbeitet hat, denke ich aber, dass es kein Zufall ist, dass die beiden Sprachen sich in dem Punkt ähneln.

    Und genau da sehe ich das Problem. Der Typ sieht das Ganze aus der Kompilerwelt. Interessanterweise hat er anscheinend auch einen C oder C++ Hintergrund, wie wohl viele von euch auch. Wieso darf es nicht unterschiedliche Definitionen auf unterschiedlichen Ebenen geben? Ja, im Bereich der Runtime/Kompiler ist es ein Call-By-Value aber auf dem abstrakten Sprach-Level ein Call-By-Referenz.

    Ich rede die ganze Zeit vom Sprachlevel. (Ich hör jetzt mal auf zu zählen, wie oft dieses "Argument" schon kam. Dürfte >5mal gewesen sein. Denkt euch mal was neues aus.)

    Ich habe Mühe hier weiter zu argumentieren, da es mir vorkommt, als ob ich jemandem erklären müsste, wieso 2 + 2 gleich 4 ist. Es ist mir völlig rätselhaft, wieso man hier sich so dermassen stur stellen will und unbedingt an irgendwelchen Definitionen festhalten möchte, auch wenn sie überhaupt keinen Mehrwert geben.

    Es hat Mehrwert.

    Könnte mir jemand sagen, wieso es relevant ist, diese Abstrahierung einem C# Programmierer sichtbar zu machen?

    Sie ist bereits sichtbar. Mein Beispiel nochmal:

    Derived obj = new Derived(); 
    Base b = obj;
    

    Vielleicht können wir darüber einen Weg finden? Wieso muss ein C# Programmierer wissen, dass hier tatsächlich das Argument kopiert wird?

    Wie erklärst du einem C#-Anfänger, dass sein Code

    void Foo(Bar bar) {
      bar = new Bar();
    }
    

    nicht das macht, was er gerne hätte?

    Vielleicht ist allgemein der Begriff Call-By-Value und Call-By-Reference nicht eindeutig genug?

    Ja, von mir aus. Als diese Begriffe eingeführt wurden, gab es m.W. noch keine Objektreferenzen als Werte. Ich glaube allerdings nicht, dass der Grund für diese Diskussionen daran liegt, dass die Begriffe nicht eindeutig wären. Sondern dass die Leute es von vornherein falsch beigebracht bekommen. Es gibt nämlich gar nicht so viele Sprachen, die Call-by-reference kennen. In den 80ern hatten wir Pascal:

    procedure foo(wertparam : integer; var refparam : integer);
    begin
      refparam := 42
    end
    

    In C gibt es kein Call-by-reference. Dort, wo man das brauchen könnte, kann man es durch Zeiger simulieren. Jetzt kommt die nächste Generation und lernt: Aha, Zeiger sind Call-by-reference. (Kannst ja mal das ANSI-C-Forum nach Problemen durchkämmen, die dadurch entstehen, dass Leute verwirrt sind, weil sie nicht verstehen, dass Zeiger by-value übergeben werden. Kommt schätzungsweise alle 2 Wochen.) Und jemand, der das verinnerlicht hat, hält natürlich auch die Übergabe von Objektreferenzen in Java für Call-by-reference.

    Dann kommt C++, wo diese Konzepte völlig transzendiert werden. Und dann auf einmal C#, das wieder ganz traditionelles By-Value und By-Reference hat, sogar out-Parameter wie in Ada. Ich kann gut verstehen, dass die Leute da durcheinander kommen. Im Gegensatz zu dir bin ich allerdings der Ansicht, dass die Denkweise, dass eine Übergabe einer Objektvariablen Call-by-reference ist, eher früher als später zu Problemen führt.



  • Bashar schrieb:

    Wie erklärst du einem C#-Anfänger, dass sein Code
    [cs]
    void Foo(Bar bar) {
    bar = new Bar();
    }

    LOL
    Genau an das Beispiel musste ich während des lesens die ganze Zeit denken.
    Daran bin ich in meinen Java-Anfängen verzweifelt.
    100 x nachgelesen...'WTF*! Da steht doch call by reference! Das muss doch gehen!!'
    Zumindest wenn man von c++ kommt, ist die Benennung verwirrend.

    (* ok, 'wtf' gabs noch nicht, hab aber was vergleichbares gedacht)


Anmelden zum Antworten