Verständnisproblem Funktionsaufruf call by value/referenz



  • hustbaer schrieb:

    Das ist soweit schon OK. Nur halt doof dass const eingespart wurde.

    Ja, ich finde das sogar sehr schön mit dem ref und out. Wenns jetzt noch const gäbe wärs eigentlich perfekt.

    hustbaer schrieb:

    Hätte aber anscheinend das Typensystem zu kompliziert gemacht. Zumindest meine ich mich zu erinnern mal sowas gelesen zu haben.

    Also Eric Lippert hält const für broken (in C/C++). Kann seiner Argumentation aber nicht so folgen, finde das ziemlich unlogisch was der da erzählt.



  • Ich halte ja grundsätzlich eher mehr als weniger von Eric Lippert. Aber das Statement das er da abgeliefert hat ist einfach nur lächerlich.

    Ja, const gibt keine Garantien.
    private und protected aber auch nicht, schon gar nicht mit der CLR.
    Hätte man die also auch streichen müssen.

    Im Endeffekt sind aber alle drei sehr praktisch um "ich schiesse mir unabsichtlich in den Fuss" zu verhindern. Um einfach ruhiger schlafen zu können.

    Und alleine dass er überhaupt anführt dass const für den "Consumer" keine Garantie ist dass sich das Objekt nicht unter seinem Hintern weg ändert, lässt mich leise vermuten dass er const überhaupt nicht verstanden hat.
    const heisst in C++ schliesslich "du darfst nicht ändern" und nicht "das wird sich nicht ändern".

    Und dann beantwortet er die Frage warum C# kein const hat damit dass sie es der CLR nicht aufs Auge drücken wollten -- behauptet dann aber gleichzeitig dass diese Entscheidung es leichter machen soll diverse Sprachen "auf die CLR zu bringen". Ähm. Ja. Klar. *facepalm*



  • hustbaer schrieb:

    Ich halte ja grundsätzlich eher mehr als weniger von Eric Lippert. Aber das Statement das er da abgeliefert hat ist einfach nur lächerlich.

    Dachte zuerst "wenn der Typ das sagt muss es ja stimmen". Aber ich glaub auch dass er es sich da ein bisschen zu leicht gemacht hat und sie in Wirklichkeit einfach keinen Bock auf const hatten 😃



  • Das ist Gewohnheitssache. Ich hab const nicht wirklich vermisst, als ich mehr C# programmiert habe. Und in C++ musste ich mich erst dran gewöhnen, fand es eine Zeit lang viel zu umständlich (muss man ja überall durchziehen, z.B. müssen die Methoden, die man aufrufen darf, auch const sein) ohne dass ich großartige Vorteile gesehen habe. Hab mich natürlich dran gewöhnt und würde in C++ darauf nicht verzichten wollen. Aber so wirklich vermissen tu ich das in C# auch nicht.



  • hustbaer schrieb:

    Bloss dummerweise kann eine Funktion die nen IFooReadOnly Parameter hat jederzeit einen Cast auf IFoo versuchen, und wenn der geklappt hat einfach die IFoo Funktionen verwenden um das Objekt zu modifizieren.

    Ähmja, das ist doch auch nicht anders in C++, wo du über const_cast<>() nach Belieben verändern kannst, wo du nicht darfst.

    hustbaer schrieb:

    Ich halte ja grundsätzlich eher mehr als weniger von Eric Lippert. Aber das Statement das er da abgeliefert hat ist einfach nur lächerlich.

    Finde ich nicht. Ich denke auch, daß er zu konservativ argumentiert, aber so wird man halt, wenn man jahrelang tolle Features in Compiler einbaut und dabei vermutlich in ein SNAFU nach dem anderen läuft, weil es halt doch nicht so einfach ist, wie sich alle Außenstehenden denken.

    Mit private und protected hast du recht, weil es keine starke Garantie ist, solange man mit Reflection trotzdem drankommt. Trotzdem sind private und protected deutlich wichtiger gewesen:

    - das wird von jedem Programmierer, der mit irgendeiner objektorientierten Sprache arbeitet, erwartet
    - über protected wird ja gestritten, aber zumindest private hat sich unbestreitbar als nützlich erwiesen
    - Java kann es, deshalb muß es in die CLR (aus demselben Grund wurde auch die kaputte Array-Kovarianz übernommen)

    hustbaer schrieb:

    Und dann beantwortet er die Frage warum C# kein const hat damit dass sie es der CLR nicht aufs Auge drücken wollten -- behauptet dann aber gleichzeitig dass diese Entscheidung es leichter machen soll diverse Sprachen "auf die CLR zu bringen". Ähm. Ja. Klar. *facepalm*

    Das ist schon so. Keine mir bekannte Sprache außer C und C++ hat sowas wie const . Wenn man const tatsächlich ins Typsystem integriert und in der BCL davon regen Gebrauch macht, müssen andere Sprachen lernen, damit umzugehen. Selbst wenn es nur eine folgenlose (d.h. von der CLR nicht erzwungene) Annotation sein soll, müssen andere Sprachen z.B. mit const /non- const -Überladungen klarkommen.

    Wie dem auch sei: ich glaube, der eigentliche Grund dafür, daß man im .NET-Umfeld sich nicht über const den Kopf zerbricht, ist, daß der Trend zu immutability geht, also " const für alle" mit den bekannten Vorteilen (konkurrenter Zugriff immer unproblematisch und so). Deshalb hatte Herr Lippert vermutlich auch die Assoziation mit den "guarantee[s] that you can actually rely upon", bei unveränderlichen Datenstrukturen hat man die nämlich.

    Mir geht es wie Mechanics; in C++ benutze ich gerne const und ärgere mich nur, wenn ich non- const -Overloads machen muß, und in C# stellt sich die Frage irgendwie gar nicht.



  • audacia schrieb:

    Ähmja, das ist doch auch nicht anders in C++, wo du über const_cast<>() nach Belieben verändern kannst, wo du nicht darfst.

    Kannst du doch gar nicht? Bzw. kannst du schon aber hast dann halt UB und dein Programm schmiert ab...



  • audacia schrieb:

    hustbaer schrieb:

    Bloss dummerweise kann eine Funktion die nen IFooReadOnly Parameter hat jederzeit einen Cast auf IFoo versuchen, und wenn der geklappt hat einfach die IFoo Funktionen verwenden um das Objekt zu modifizieren.

    Ähmja, das ist doch auch nicht anders in C++, wo du über const_cast<>() nach Belieben verändern kannst, wo du nicht darfst.

    Oha.
    Der riesen Unterschied ist dass const_cast sowie C-Style-Casts bzw. Function-Style-Casts in C++ sehr verpönt sind, und man sofort "hoppla!" denkt wenn man es sieht. Wohingegen Casts von einem Interface zum anderen in C# überhaupt nicht verpönt sind.

    audacia schrieb:

    Trotzdem sind private und protected deutlich wichtiger gewesen: (...)

    Ich bestreite ja gar nicht dass private und protected wichtiger sind. Ich meine nur: das Argument vonwegen "not enforcable" kann er sich einrexen. Bzw. es ist für mich weder hinreichend noch sonst irgendwie interessant wenn ich darüber nachdenke ob const umgesetzt werden soll oder nicht.
    Und vor allem: es spricht ja durchaus nichts dagegen es besser zu machen. Hat ja keiner verlangt dass const gleich "kaputt" übernommen wird wie es in C++ umgesetzt wurde.
    Was aber, neben anderem Unsinn, von Lippert unterstellt wird.

    Kurz: ich bin mit seiner Antwort nicht einverstanden.

    Ich bin durchaus der Meinung dass man sinnvoll gegen const argumentieren kann. Nur so sieht so ein Argument eben nicht aus. Und wenn er nix sinnvolles zu sagen hat, warum meldet er sich dann überhaupt?
    Das ist inetwa so sinnvoll wie die Deppen die auf Amazon auf eine Frage zu einem Produkt antworten "weiss ich leider nicht, sorry".
    (Ja, ich weiss wie diese Antworten auf Amazon zustande kommen, bloss ein bisschen Hirn einschalten wäre echt nicht zu viel verlangt.)



  • happystudent schrieb:

    audacia schrieb:

    Ähmja, das ist doch auch nicht anders in C++, wo du über const_cast<>() nach Belieben verändern kannst, wo du nicht darfst.

    Kannst du doch gar nicht? Bzw. kannst du schon aber hast dann halt UB und dein Programm schmiert ab...

    Klar kannst du.
    UB ist es nur wenn das Objekt selbst const ist.
    Wenn dagegen einfach nur ein T const* , auf ein T was selbst gar nicht const ist, übergeben wurde, dann kann man problemlos das const wegcasten und in dem T drinnen rummalen.



  • happystudent schrieb:

    aber hast dann halt UB und dein Programm schmiert ab...

    Aus UB folgt nicht, daß dein Programm abstürzt. Ein aggressiv optimierender Compiler mag zwar UB zum Anlaß für relativ absurde Optimierungen nehmen (indem er, grob gesagt, annimmt, daß der UB-Fall nie eintritt), aber es ist doch recht wahrscheinlich, daß genau das passiert, was man naiverweise erwarten würde.

    hustbaer schrieb:

    Der riesen Unterschied ist dass const_cast sowie C-Style-Casts bzw. Function-Style-Casts in C++ sehr verpönt sind, und man sofort "hoppla!" denkt wenn man es sieht. Wohingegen Casts von einem Interface zum anderen in C# überhaupt nicht verpönt sind.

    Mit dem Argument habe ich so halb gerechnet 🙂 Allerdings sehe ich das anders. Es gibt ein paar Stellen, wo Casts in C# nötig und legitim sind:

    - im Zusammenhang mit type erasure ( Control.Tag )
    - in den Innereien von irgendwelchem Bibliothekscode, der weiß, was er da tut (d.h. Casts auf internen Typen)
    - in Urzeitrelikten aus .NET 1.x, wo es noch keine Generics gab (das sind auch meistens die Stellen, wo man type erasure verwenden muß)
    - im params Foo[] items -Overload einer IEnumerable<Foo> items -Methode ist ein Cast nach IEnumerable<Foo> erlaubt

    Abgesehen von dieser wahrscheinlich nicht vollständigen Liste beäuge ich jeden einzelnen Cast mißtrauisch, genau wie ich einen const_cast<>() , dynamic_cast<>() oder reinterpret_cast<>() in C++ beäuge, wenn sie nicht auf den jeweiligen Ausnahmelisten stehen.

    hustbaer schrieb:

    Ich meine nur: das Argument vonwegen "not enforcable" kann er sich einrexen. Bzw. es ist für mich weder hinreichend noch sonst irgendwie interessant wenn ich darüber nachdenke ob const umgesetzt werden soll oder nicht.

    Dasselbe Argument spielt auch eine Rolle in der Diskussion auf Codeplex, ob man non-nullable references einführen soll (mit einem ! -Suffix analog zu ? für nullbare Werttypen). Hast du die verfolgt? Meiner Erinnerung nach sagten sie "wir können das [ohne eine tiefgreifende Änderung in der CLR] nicht erzwingen, deshalb sollte man das nicht in die Sprache einführen, sondern über Annotationen und Analysetools lösen".

    hustbaer schrieb:

    Und vor allem: es spricht ja durchaus nichts dagegen es besser zu machen. Hat ja keiner verlangt dass const gleich "kaputt" übernommen wird wie es in C++ umgesetzt wurde.
    Was aber, neben anderem Unsinn, von Lippert unterstellt wird.

    Gut, das stimmt. Ich glaube, eine nicht-kaputte (also von der CLR forcierbare) Lösung wird allerdings ziemlich teuer, und der Nutzen zu diesem Zeitpunkt bleibt vernachlässigbar, weil die BCL das Konzept nicht verwendet. Ähnliches Problem für nicht-nullbare Referenzen.



  • hustbaer schrieb:

    Klar kannst du.
    UB ist es nur wenn das Objekt selbst const ist.
    Wenn dagegen einfach nur ein T const* , auf ein T was selbst gar nicht const ist, übergeben wurde, dann kann man problemlos das const wegcasten und in dem T drinnen rummalen.

    Ups, stimmt da hab ich mich zu weit aus dem Fenster gelehnt.^^

    Aber man könnte es ja trotzdem anbieten, nur halt den (ohnehin bösen) const_cast weglassen.


Anmelden zum Antworten