Verständnisproblem Funktionsaufruf call by value/referenz
-
ref
undout
beziehen sich bei Reference-Types dann auf die Referenz.Also Beispiel
SomeRefType foo; bar.SomeFunction(out foo); foo.DoFoo(); // OK, da per out übergeben und damit jetzt initialisiert
Das ist soweit schon OK. Nur halt doof dass
const
eingespart wurde.
Hätte aber anscheinend das Typensystem zu kompliziert gemacht. Zumindest meine ich mich zu erinnern mal sowas gelesen zu haben.
-
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
undprotected
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 aufIFoo
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
undprotected
hast du recht, weil es keine starke Garantie ist, solange man mit Reflection trotzdem drankommt. Trotzdem sindprivate
undprotected
deutlich wichtiger gewesen:- das wird von jedem Programmierer, der mit irgendeiner objektorientierten Sprache arbeitet, erwartet
- überprotected
wird ja gestritten, aber zumindestprivate
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 manconst
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. mitconst
/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 aufIFoo
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 dassconst_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
undprotected
deutlich wichtiger gewesen: (...)Ich bestreite ja gar nicht dass
private
undprotected
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 selbstconst
ist.
Wenn dagegen einfach nur einT const*
, auf einT
was selbst gar nichtconst
ist, übergeben wurde, dann kann man problemlos dasconst
wegcasten und in demT
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ß)
- imparams Foo[] items
-Overload einerIEnumerable<Foo> items
-Methode ist ein Cast nachIEnumerable<Foo>
erlaubtAbgesehen von dieser wahrscheinlich nicht vollständigen Liste beäuge ich jeden einzelnen Cast mißtrauisch, genau wie ich einen
const_cast<>()
,dynamic_cast<>()
oderreinterpret_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 selbstconst
ist.
Wenn dagegen einfach nur einT const*
, auf einT
was selbst gar nichtconst
ist, übergeben wurde, dann kann man problemlos dasconst
wegcasten und in demT
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.