Welchen Sinn hat der in-Modifikator für Klassen?

9

C # 7.2 führt den Parameter in für Parameter ein, der für Strukturen und insbesondere für Readonly-Strukturen vollkommen Sinn macht.

Es ist auch erlaubt, es für einen Referenztyp zu verwenden

%Vor%

Da Referenztypen standardmäßig per Referenz übergeben werden, ist der in im obigen Beispiel nur ein redundanter Modifikator?

value = null ist verboten, wenn Sie in verwenden, bedeutet dies, dass es auch die Kopie der Referenzadresse erspart, indem nur die ursprüngliche Referenz an den Heapspeicherort übergeben und Änderungen blockiert werden?

    
user4388177 07.03.2018, 10:25
quelle

3 Antworten

9

in wird genau wie ref nach IL kompiliert, außer in Argument ist mit IsReadOnly attribute gekennzeichnet.

Das bedeutet in verhält sich genau wie ref , aber der Compiler (nicht die Laufzeit) erzwingt, dass Sie in argument keinen Wert zuweisen.

Also, wie Sie richtig angemerkt haben - in reference-type Argument wird als Referenz übergeben (was bedeutet, dass die Referenz nicht kopiert wird und auf den ursprünglichen Speicherort zeigt), aber der Compiler verhindert, dass Sie sie ändern. Ich sehe nicht viel davon für Referenztypen, aber es wird nicht schaden, zumindest aus Gründen der Konsistenz.

    
Evk 07.03.2018, 10:39
quelle
2

Nach dem, was ich von offizieller Dokumentation verstehe bedeutet, dass an die Methode übergebene Argumente nicht innerhalb der Methode selbst geändert werden:

  

Das Schlüsselwort in gibt an, dass Sie den Parameter durch Verweis übergeben und die aufgerufene Methode den daran übergebenen Wert nicht ändert.

Wenn das Schlüsselwort in mit Werttypen verwendet wird, bedeutet dies, dass das Argument nicht als Wert übergeben wird (dh es wird eine neue Kopie des Werts erstellt), sondern als Referenz übergeben - so wird unnötiges Kopieren vermieden.

    
Zohar Peled 07.03.2018 10:40
quelle
1

Während die anderen beiden Antworten korrekt sind, dass in -Parameter als ref -Parameter im resultierenden IL enden, sollte darauf geachtet werden, dass dies verhindert, dass der Wert kopiert wird. Dies gilt nur für Readonly-Strukturen.

Um dies zu demonstrieren, betrachten Sie den folgenden Code:

%Vor%

Da wir s1 als Referenz übergeben, könnte man vernünftigerweise annehmen, dass S1Foo beim Aufruf von ChangeA dann den Inhalt von s1 ändert. Dies geschieht nicht, wenn . Der Grund dafür ist, dass der Wert s1 kopiert und eine Kopie als Referenz übergeben wird, um solche Modifikationen von Strukturen über in -Parameter zu verhindern.

Wenn wir das resultierende IL dekompilieren, sehen Sie, dass der Code endet als:

%Vor%

Wenn wir jedoch ähnlichen Code mit readonly struct schreiben, wird kein Kopieren ausgeführt. Ich sage ähnlich, da es nicht möglich ist, denselben Code zu schreiben, da Felder und Eigenschaften nur in einer schreibgeschützten Struktur gelesen werden müssen (der Hinweis ist im Namen):

%Vor%

Dann keine Kopie erfolgt in dem resultierenden IL .

Also zusammenfassend:

  1. in ist effektiv ein readonly ref ,
  2. Der Wert (oder die Referenz) wird als Referenz übergeben,
  3. Der Compiler verhindert, dass Felder und Eigenschaften dieser Referenz geändert werden, um die Readonly-ness,
  4. , zu erzwingen
  5. Um die schreibgeschützte Natur des Parameters weiter zu erzwingen, werden nicht-readonly-Strukturen kopiert, bevor ein Verweis auf die Kopie an die Methode übergeben wird. Dies tritt nicht bei Readonly-Strukturen auf.
David Arno 07.03.2018 13:43
quelle

Tags und Links