El comportamiento es extremadamente similar al Array.Resize
método en .NET. Para comprender lo que está sucediendo, puede ser útil mirar el historial del .
token en C, C ++, Java, C # y Swift.
En C, una estructura no es más que una agregación de variables. Aplicando el .
a una variable de tipo de estructura accederá a una variable almacenada dentro de la estructura. Los punteros a los objetos no contienen agregaciones de variables, sino que las identifican . Si uno tiene un puntero que identifica una estructura, el ->
operador puede usarse para acceder a una variable almacenada dentro de la estructura identificada por el puntero.
En C ++, las estructuras y clases no solo agregan variables, sino que también pueden adjuntarles código. El uso .
para invocar un método le pedirá a ese método que actúe sobre el contenido de la variable en sí ; El uso ->
de una variable que identifica un objeto le pedirá a ese método que actúe sobre el objeto identificado por la variable.
En Java, todos los tipos de variables personalizadas simplemente identifican objetos, e invocar un método sobre una variable le dirá al método qué objeto identifica la variable. Las variables no pueden contener ningún tipo de tipo de datos compuesto directamente, ni hay ningún medio por el cual un método pueda acceder a una variable sobre la que se invoca. Estas restricciones, aunque semánticamente limitantes, simplifican enormemente el tiempo de ejecución y facilitan la validación del código de bytes; tales simplificaciones redujeron la sobrecarga de recursos de Java en un momento en que el mercado era sensible a tales problemas y, por lo tanto, lo ayudaron a ganar tracción en el mercado. También significaban que no había necesidad de un token equivalente al .
utilizado en C o C ++. Aunque Java podría haber usado ->
de la misma manera que C y C ++, los creadores optaron por usar un solo carácter.
ya que no era necesario para ningún otro propósito.
En C # y otros lenguajes .NET, las variables pueden identificar objetos o contener tipos de datos compuestos directamente. Cuando se usa en una variable de un tipo de datos compuesto, .
actúa sobre el contenido de la variable; cuando se usa en una variable de tipo de referencia, .
actúa sobre el objeto identificadopor esto. Para algunos tipos de operaciones, la distinción semántica no es particularmente importante, pero para otros sí lo es. Las situaciones más problemáticas son aquellas en las que un método de tipo de datos compuesto que modificaría la variable sobre la que se invoca, se invoca en una variable de solo lectura. Si se intenta invocar un método en un valor o variable de solo lectura, los compiladores generalmente copiarán la variable, dejarán que el método actúe sobre eso y descartarán la variable. Esto generalmente es seguro con métodos que solo leen la variable, pero no es seguro con métodos que le escriben. Desafortunadamente, .does aún no tiene ningún medio para indicar qué métodos se pueden usar de manera segura con dicha sustitución y cuáles no.
En Swift, los métodos en agregados pueden indicar expresamente si modificarán la variable sobre la que se invocan, y el compilador prohibirá el uso de métodos de mutación en variables de solo lectura (en lugar de hacer que muten copias temporales de la variable que luego descartarse). Debido a esta distinción, usar el.
token para llamar a métodos que modifican las variables sobre las que se invocan es mucho más seguro en Swift que en .NET. Desafortunadamente, el hecho de que el mismo .
token se use para ese propósito como para actuar sobre un objeto externo identificado por una variable significa que existe la posibilidad de confusión.
Si tuviera una máquina del tiempo y volviera a la creación de C # y / o Swift, uno podría evitar retroactivamente gran parte de la confusión que rodea a estos problemas haciendo que los lenguajes usen los tokens .
y ->
de una manera mucho más cercana al uso de C ++. Los métodos tanto de los agregados como de los tipos de referencia podrían usarse .
para actuar sobre la variable sobre la que fueron invocados, y ->
para actuar sobre una valor (para compuestos) o la cosa identificada por ellos (para tipos de referencia). Sin embargo, ninguno de los dos idiomas está diseñado de esa manera.
En C #, la práctica normal de un método para modificar una variable sobre la que se invoca es pasar la variable como ref
parámetro a un método. Por lo tanto, llamar Array.Resize(ref someArray, 23);
cuando someArray
identifica una matriz de 20 elementos hará someArray
que se identifique una nueva matriz de 23 elementos, sin afectar la matriz original. El uso de ref
deja en claro que se debe esperar que el método modifique la variable sobre la que se invoca. En muchos casos, es ventajoso poder modificar variables sin tener que usar métodos estáticos; Direcciones rápidas que significa mediante el uso de .
sintaxis. La desventaja es que pierde claridad sobre qué métodos actúan sobre las variables y qué métodos actúan sobre los valores.