type entre diferencia data c# this value-type

c# - entre - Cambiar la ''this'' variable de los tipos de valor



struct c# (3)

Aparentemente puede cambiar this valor desde cualquier lugar de su estructura (pero no en clases):

struct Point { public Point(int x, int y) { this = new Point(); X = x; Y = y; } int X; int Y; }

No he visto esto antes ni lo necesitaba. ¿Por qué uno querría hacer eso alguna vez? Eric Lippert nos recuerda que una característica debe estar justificada para ser implementada. ¿Qué gran caso de uso podría justificar esto? ¿Hay algún escenario donde esto es invaluable? No pude encontrar ninguna documentación en él 1 .

Además, para los constructores de llamadas ya existe una sintaxis alternativa más conocida, por lo que esta característica a veces es redundante:

public Point(int x, int y) : this() { X = x; Y = y; }

Encontré esta característica en un ejemplo en Jeffrey Richter''s CLR via C # 4th edition .
1) Aparentemente está en la especificación C # .


Además, no pude encontrar ninguna documentación sobre esto.

¿Intentó buscar en la especificación C #? Porque puedo encontrar documentación sobre él (7.6.7):

  • Cuando this se usa en una expresión primaria dentro de un constructor de instancia de una estructura, se clasifica como una variable. El tipo de la variable es el tipo de instancia (§10.3.1) de la estructura dentro de la cual ocurre el uso, y la variable representa la estructura que se está construyendo. this variable de un constructor de instancia de una estructura se comporta exactamente igual que un parámetro de out del tipo de estructura; en particular, esto significa que la variable debe asignarse definitivamente en cada ruta de ejecución del constructor de instancia.

  • Cuando this se usa en una expresión primaria dentro de un método de instancia o acceso de instancia de una estructura, se clasifica como una variable. El tipo de la variable es el tipo de instancia (§10.3.1) de la estructura dentro de la cual ocurre el uso.

    • Si el método o el descriptor de acceso no es un iterador (§10.14), this variable representa la estructura para la que se invocó el método o el descriptor, y se comporta exactamente igual que un parámetro ref del tipo de estructura.
    • Si el método o el descriptor de acceso es un iterador, this variable representa una copia de la estructura para la que se invocó el método o el descriptor de acceso, y se comporta exactamente igual que un parámetro de valor del tipo de estructura.

En cuanto a un caso de uso para él, no puedo pensar inmediatamente en muchos: lo único que tengo es si los valores que desea asignar en el constructor son caros de computar, y usted tiene un valor en caché que quiero copiar this , puede ser conveniente.


¡Buena pregunta!

Los tipos de valor son, por definición, copiados por valor. Si this no fuera en realidad un alias de una ubicación de almacenamiento, entonces el constructor estaría inicializando una copia en lugar de inicializar la variable que pretende inicializar. ¡Lo que haría al constructor algo menos útil! Y de manera similar para los métodos; sí, las estructuras mutables son malas, pero si vas a hacer una estructura mutable nuevamente, this tiene que ser la variable que está siendo mutada, no una copia de su valor.

El comportamiento que está describiendo es una consecuencia lógica de esa decisión de diseño: dado que alias una variable, puede asignarla, lo mismo que puede asignar a cualquier otra variable.

Es algo extraño asignarlo directamente así, en lugar de asignarlo a sus campos. ¡Es aún más extraño asignarlo directamente y luego sobrescribir el 100% de esa asignación!

Un diseño alternativo que evitaría hacer de this un alias para el almacenamiento del receptor sería asignarlo al pool de almacenamiento a corto plazo, inicializarlo en el controlador y luego devolverlo por valor. La desventaja de ese enfoque es que hace que las optimizaciones de copiado sean prácticamente imposibles, y hace que los códigos y métodos sean extrañamente inconsistentes.


Una ubicación de almacenamiento de tipo de valor en una agregación de ubicaciones de almacenamiento que comprende los campos público y privado de ese tipo. Al pasar un tipo de valor, un parámetro ordinario (valor) pasará física y semánticamente el contenido de todos sus campos. Al pasar un tipo de valor como un parámetro ref se pasa semánticamente el contenido de todos sus campos, aunque se usa un solo "byref" para pasarlos a todos.

Llamar a un método en una estructura equivale a pasar la estructura (y, por lo tanto, todos sus campos) como un parámetro ref , excepto por una arruga: normalmente, ni C # ni vb.net permitirán que se pase un valor de solo lectura como ref parámetro. Sin embargo, ambos permitirán que los métodos struct se invoquen en valores de solo lectura o valores temporales. Lo hacen haciendo una copia de toda la estructura (y, por lo tanto, todos sus campos), y luego pasan esa copia como un parámetro de ref .

Debido a este comportamiento, algunas personas llaman a las estructuras mutables "malvadas", pero lo único que es malo es el hecho de que ni C # ni vb.net definen ningún atributo para indicar si un miembro o propiedad de una estructura debe ser invocable en cosas que no pueden pasar directamente por ref .