Das Verhalten ist der Array.Resize
Methode in .NET sehr ähnlich . Um zu verstehen, was los ist, kann es hilfreich sein, den Verlauf des .
Tokens in C, C ++, Java, C # und Swift zu betrachten.
In C ist eine Struktur nichts anderes als eine Aggregation von Variablen. Durch Anwenden von .
auf eine Variable vom Strukturtyp wird auf eine in der Struktur gespeicherte Variable zugegriffen. Zeiger auf Objekte nicht halten Aggregationen von Variablen, aber identifizieren sie. Wenn man einen Zeiger hat, der eine Struktur identifiziert, kann der ->
Operator verwendet werden, um auf eine Variable zuzugreifen, die in der durch den Zeiger identifizierten Struktur gespeichert ist.
In C ++ aggregieren Strukturen und Klassen nicht nur Variablen, sondern können ihnen auch Code hinzufügen. Wenn Sie .
eine Methode aufrufen, wird diese Methode für eine Variable aufgefordert, auf den Inhalt der Variablen selbst zu reagieren. Wenn Sie ->
eine Variable verwenden, die ein Objekt identifiziert, wird diese Methode aufgefordert, auf das durch die Variable identifizierte Objekt zu reagieren.
In Java identifizieren alle benutzerdefinierten Variablentypen einfach Objekte, und das Aufrufen einer Methode für eine Variable teilt der Methode mit, welches Objekt von der Variablen identifiziert wird. Variablen können weder einen zusammengesetzten Datentyp direkt enthalten, noch gibt es Mittel, mit denen eine Methode auf eine Variable zugreifen kann, für die sie aufgerufen wird. Diese Einschränkungen sind zwar semantisch einschränkend, vereinfachen jedoch die Laufzeit erheblich und erleichtern die Bytecode-Validierung. Solche Vereinfachungen reduzierten den Ressourcenaufwand von Java zu einer Zeit, als der Markt für solche Probleme sensibel war, und trugen so dazu bei, auf dem Markt Fuß zu fassen. Sie bedeuteten auch, dass kein Token erforderlich war, das dem .
in C oder C ++ verwendeten entspricht. Obwohl Java ->
genauso wie C und C ++ hätte verwendet werden können, entschieden sich die Ersteller für die Verwendung von Einzelzeichen.
da es für keinen anderen Zweck benötigt wurde.
In C # und anderen .NET-Sprachen können Variablen entweder Objekte identifizieren oder zusammengesetzte Datentypen direkt enthalten. Bei Verwendung für eine Variable eines zusammengesetzten Datentyps wird .
auf den Inhalt der Variablen reagiert. Wenn es für eine Variable vom Referenztyp verwendet wird, .
wirkt es auf das identifizierte Objektvon ihm. Für einige Arten von Operationen ist die semantische Unterscheidung nicht besonders wichtig, für andere jedoch. Die problematischsten Situationen sind solche, in denen die Methode eines zusammengesetzten Datentyps, die die Variable ändern würde, für die er aufgerufen wird, für eine schreibgeschützte Variable aufgerufen wird. Wenn versucht wird, eine Methode für einen schreibgeschützten Wert oder eine schreibgeschützte Variable aufzurufen, kopieren Compiler die Variable im Allgemeinen, lassen die Methode darauf reagieren und verwerfen die Variable. Dies ist im Allgemeinen sicher bei Methoden, die nur die Variable lesen, aber nicht sicher bei Methoden, die darauf schreiben. Leider hat .does noch keine Möglichkeit anzugeben, welche Methoden mit einer solchen Substitution sicher verwendet werden können und welche nicht.
In Swift können Methoden für Aggregate ausdrücklich angeben, ob sie die Variable ändern, für die sie aufgerufen werden, und der Compiler verbietet die Verwendung von Mutationsmethoden für schreibgeschützte Variablen (anstatt temporäre Kopien der Variablen zu mutieren, die dann mutieren weggeworfen werden). Aufgrund dieser Unterscheidung ist die Verwendung des .
Tokens zum Aufrufen von Methoden, die die Variablen ändern, für die sie aufgerufen werden, in Swift viel sicherer als in .NET. Leider bedeutet die Tatsache, dass .
zu diesem Zweck dasselbe Token verwendet wird, um auf ein externes Objekt einzuwirken, das durch eine Variable identifiziert wird, dass die Möglichkeit einer Verwirrung bestehen bleibt.
Wenn man eine Zeitmaschine hätte und zur Erstellung von C # und / oder Swift zurückkehren würde, könnte man rückwirkend einen Großteil der Verwirrung vermeiden, die mit solchen Problemen verbunden ist, indem Sprachen die Token .
und und ->
Token auf eine Weise verwenden, die der C ++ - Verwendung viel näher kommt. Methoden sowohl von Aggregaten als auch von Referenztypen könnten verwendet werden .
, um auf die Variable zu wirken, auf die sie aufgerufen wurden, und ->
um auf einen Wert (für Verbundwerkstoffe) oder das dadurch identifizierte Objekt (für Referenztypen) zu wirken. Keine der beiden Sprachen ist jedoch so gestaltet.
In C # besteht die übliche Praxis für eine Methode zum Ändern einer Variablen, für die sie aufgerufen wird, darin, die Variable als ref
Parameter an eine Methode zu übergeben. Array.Resize(ref someArray, 23);
Wenn Sie also someArray
ein Array mit 20 Elementen aufrufen someArray
, wird ein neues Array mit 23 Elementen identifiziert, ohne dass dies Auswirkungen auf das ursprüngliche Array hat. Die Verwendung von ref
macht deutlich, dass von der Methode erwartet werden sollte, dass sie die Variable ändert, für die sie aufgerufen wird. In vielen Fällen ist es vorteilhaft, Variablen ändern zu können, ohne statische Methoden verwenden zu müssen. Schnelle Adressen, dh .
Syntax. Der Nachteil ist, dass es an Klarheit verliert, welche Methoden auf Variablen und welche Methoden auf Werte einwirken.