Eine freundschaftliche Debatte mit einem Kollegen darüber führen. Wir haben einige Gedanken darüber, aber fragen uns, was die SO-Menge darüber denkt?
c#
immutability
language-design
readonly
Brian Genisio
quelle
quelle
Antworten:
Ein Grund ist, dass es keine CLR-Unterstützung für einen schreibgeschützten lokalen gibt. Readonly wird zunächst in den CLR / CLI-Opcode übersetzt. Dieses Flag kann nur auf Felder angewendet werden und hat keine Bedeutung für ein lokales. In der Tat wird die Anwendung auf einen lokalen Code wahrscheinlich zu nicht überprüfbarem Code führen.
Dies bedeutet nicht, dass C # dies nicht tun konnte. Aber es würde dem gleichen Sprachkonstrukt zwei verschiedene Bedeutungen geben. Die Version für Einheimische hätte keine CLR-äquivalente Zuordnung.
quelle
readonly
Schlüsselwort für Felder muss von der CLI unterstützt werden, da seine Auswirkung für andere Assemblys sichtbar ist . Es würde lediglich bedeuten, dass die Variable zur Kompilierungszeit nur eine Zuordnung in der Methode hat.const
(was in C ++ eher C #readonly
als C # ähneltconst
, obwohl es beide Rollen spielen kann). C ++ unterstützt jedochconst
lokale automatische Variablen. Daher ist das Fehlen einer CLR-Unterstützung für ein C #readonly
für eine lokale Variable irrelevant.using
undout
genau das tun und die Welt nicht zusammenbricht.Ich denke, es ist ein schlechtes Urteil von Seiten der C # -Architekten. Der schreibgeschützte Modifikator für lokale Variablen hilft bei der Aufrechterhaltung der Programmkorrektheit (genau wie bei Asserts) und kann dem Compiler möglicherweise dabei helfen, den Code zu optimieren (zumindest bei anderen Sprachen). Die Tatsache, dass es derzeit in C # nicht zulässig ist, ist ein weiteres Argument dafür, dass einige der "Merkmale" von C # lediglich eine Durchsetzung des persönlichen Codierungsstils seiner Ersteller sind.
quelle
Bei der Beantwortung von Jareds Antwort müsste es sich wahrscheinlich nur um eine Funktion zur Kompilierungszeit handeln. Der Compiler würde Ihnen verbieten, nach der ersten Deklaration (die eine Zuweisung enthalten müsste) in die Variable zu schreiben.
Kann ich darin Wert sehen? Potenziell - aber nicht viel, um ehrlich zu sein. Wenn Sie nicht leicht erkennen können, ob eine Variable an anderer Stelle in der Methode zugewiesen wird oder nicht, ist Ihre Methode zu lang.
Für was es wert ist , hat Java diese Funktion (mit dem
final
Modifikator) , und ich habe sehr selten es als in den Fällen verwendet , um andere zu sehen , wo es hat verwendet werden , um die Variable zu ermöglichen , von einer anonymen inneren Klasse erfaßt werden - und wo es ist verwendet, gibt es mir eher einen Eindruck von Unordnung als nützliche Informationen.quelle
readonly
/final
Werte von Variablen mit ihrenval
undvar
Schlüsselwörtern. Im Scala-Code werden lokaleval
s sehr häufig verwendet (und werden tatsächlich lokalenvar
s vorgezogen ). Ich vermute, dass die Hauptgründe dafür, dass derfinal
Modifikator in Java nicht häufiger verwendet wird, a) Unordnung und b) Faulheit sind.readonly
wäre dies nicht übermäßig wichtig. Andererseitsreadonly
würde der Compiler für lokale Variablen, die in Abschlüssen verwendet werden, in vielen Fällen effizienteren Code generieren lassen. Wenn die Ausführung in einen Block eintritt, der einen Abschluss enthält, muss der Compiler derzeit ein neues Heap-Objekt für die geschlossenen Variablen erstellen, selbst wenn kein Code ausgeführt wird, der den Abschluss verwenden würde . Wenn eine Variable schreibgeschützt wäre, könnte Code außerhalb des Abschlusses eine normale Variable verwenden. Nur wenn ein Delegat für die Schließung erstellt wird ...Ein Vorschlag, der nur Einheimische und Parameter enthält, wurde vom C # 7-Designteam kurz besprochen. Aus C # Design Meeting Notes für den 21. Januar 2015 :
Die Diskussion wird im C # Language Design Repo fortgesetzt. Stimmen Sie ab, um Ihre Unterstützung zu zeigen. https://github.com/dotnet/csharplang/issues/188
quelle
Es ist ein Versehen für C # -Sprachendesigner. F # hat das Schlüsselwort val und basiert auf CLR. Es gibt keinen Grund, warum C # nicht dieselbe Sprachfunktion haben kann.
quelle
Ich war dieser Mitarbeiter und es war nicht freundlich! (Ich mache nur Spaß)
Ich würde die Funktion nicht eliminieren, da es besser ist, kurze Methoden zu schreiben. Es ist ein bisschen so, als würde man sagen, man sollte keine Threads verwenden, weil sie hart sind. Gib mir das Messer und lass mich dafür verantwortlich sein, dass ich mich nicht schneide.
Persönlich wollte ich ein anderes Schlüsselwort vom Typ "var" wie "inv" (invarient) oder "rvar", um Unordnung zu vermeiden. Ich habe in letzter Zeit F # studiert und finde die unveränderliche Sache ansprechend.
Ich wusste nie, dass Java das hat.
quelle
Ich möchte lokale schreibgeschützte Variablen auf die gleiche Weise wie lokale const- Variablen. Aber es hat weniger Priorität als andere Themen.
Vielleicht ist seine Priorität der gleiche Grund für C # -Designer, diese Funktion (noch!) Nicht zu implementieren. Es sollte jedoch einfach (und abwärtskompatibel) sein, lokale schreibgeschützte Variablen in zukünftigen Versionen zu unterstützen.
quelle
Schreibgeschützt bedeutet, dass die Instanzvariable nur im Konstruktor festgelegt werden kann. Wenn eine Variable lokal deklariert wird, hat sie keine Instanz (sie befindet sich nur im Gültigkeitsbereich) und kann vom Konstruktor nicht berührt werden.
quelle
Ich weiß, das beantwortet nicht das Warum Ihrer Frage. Wie auch immer, diejenigen, die diese Frage lesen, werden den folgenden Code dennoch zu schätzen wissen.
Wenn Sie sich beim Überschreiben einer lokalen Variablen, die nur einmal festgelegt werden soll, wirklich darum kümmern, sich selbst in den Fuß zu schießen, und Sie sie nicht zu einer global zugänglichen Variablen machen möchten, können Sie so etwas tun.
Anwendungsbeispiel:
Vielleicht nicht so wenig Code wie,
rvar rInt = 5
aber es funktioniert.quelle
Sie können schreibgeschützte lokale Variablen in C # deklarieren, wenn Sie den interaktiven C # -Compiler verwenden
csi
:Sie können auch schreibgeschützte lokale Variablen im Skriptformat deklarieren
.csx
.quelle
message
handelt es sich hier nicht um eine Variable, sondern um ein Feld. Dies ist kein Nitpicking, da die Unterscheidung auch in interaktivem C # eindeutig vorhandenint x; Console.WriteLine(x)
ist : ist legal interaktives C # (weilx
es ein Feld ist und implizit initialisiert wird), abervoid foo() { int x; Console.WriteLine(x); }
nicht (weilx
es eine Variable ist und verwendet wird, bevor es zugewiesen wird). AußerdemExpression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType
wird sich herausstellen, dassx
es sich wirklich um ein Feld und nicht um eine lokale Variable handelt.c # hat bereits eine schreibgeschützte Variable, wenn auch in einer etwas anderen Syntax:
Betrachten Sie die folgenden Zeilen:
Vergleichen mit:
Zugegeben, die erste Lösung könnte möglicherweise weniger zu schreibender Code sein. Das zweite Snippet macht das Readonly jedoch explizit, wenn auf die Variable verwiesen wird.
quelle
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");
.verwenden
const
Schlüsselwort, um eine schreibgeschützte Variable zu erstellen.Referenz: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
quelle
const
bei dem die Variable möglicherweise nur während der Initialisierung zugewiesen wird, nicht für den csharp-Stil,const
bei dem nur Ausdrücke zur Kompilierungszeit verwendet werden dürfen. ZB können Sie nicht tun,const object c = new object();
aber einreadonly
Einheimischer würde Ihnen erlauben, dies zu tun.Ich denke, das liegt daran, dass eine Funktion mit einer schreibgeschützten Variablen möglicherweise nie aufgerufen wird und wahrscheinlich etwas außerhalb des Gültigkeitsbereichs liegt, und wann müssten Sie dies tun?
quelle