=============
ACTUALIZACIÓN: He utilizado esta respuesta como la base para esta entrada de blog:
Why do ref and out parameters not allow type variation?
Ver la página del blog para obtener más comentario sobre este tema. Gracias por la gran pregunta.
=============
Supongamos que tiene clases Animal
, Mammal
, Reptile
, Giraffe
, Turtle
y Tiger
, con las relaciones de subclases obvias.
Supongamos que tiene un método void M(ref Mammal m)
. M
puede leer y escribir m
.
Se puede pasar una variable de tipo Animal
-M
?
No. Esa variable podría contener un Turtle
, pero M
asumirá que contenga sólo mamíferos. Un Turtle
no es un Mammal
.
Conclusión 1: ref
los parámetros no se pueden hacer "más grandes". (Hay más animales que los mamíferos, por lo que la variable es cada vez "más grande", ya que puede contener más cosas.)
Se puede pasar una variable de tipo Giraffe
a M
?
Nº M
puede escribir en m
, y M
puede ser que desee escribir una Tiger
en m
. Ahora ha puesto un Tiger
en una variable que en realidad es del tipo Giraffe
.
Conclusión 2: ref
los parámetros no se pueden hacer "más pequeños".
Considera ahora N(out Mammal n)
.
¿Se puede pasar una variable del tipo Giraffe
al N
?
Nº N
puede escribir en n
y N
puede ser que desee escribir una Tiger
.
Conclusión 3: out
los parámetros no pueden hacerse "más pequeños".
Se puede pasar una variable de tipo Animal
-N
?
Hmm.
Bueno, ¿por qué no? N
no se puede leer desde n
, solo puede escribir en él, ¿no? Usted escribe un Tiger
en una variable del tipo Animal
y ya está todo listo, ¿verdad?
Wrong. La regla no es "N
solo puede escribir en n
".
Las reglas son, en pocas palabras:
1) N
tiene que escribir en n
antes N
vuelve normalmente. (Si N
tiros, todas las apuestas están apagadas.)
2) N
tiene que escribir algo a n
antes de que se lee algo de n
.
que permite esta secuencia de eventos:
- declarar un campo de tipo
x
Animal
.
- Pase
x
como un parámetro out
a N
.
N
escribe Tiger
en n
, que es un alias de x
.
- En otro hilo, alguien escribe
Turtle
en x
.
N
intenta leer el contenido de n
, y descubre un Turtle
en lo que cree que es una variable del tipo Mammal
.
Es evidente que queremos que sea ilegal.
Conclusión 4: out
los parámetros no se pueden hacer "más grandes".
Conclusión final: Ni ref
ni out
parámetros pueden variar sus tipos. Hacer lo contrario es romper la seguridad del tipo verificable.
Si estos problemas en la teoría de tipos básicos le interesan, considere leer my series on how covariance and contravariance work in C# 4.0.
+1. Gran explicación usando ejemplos de clase del mundo real que demuestran claramente los problemas (es decir, explicar con A, B y C hace que sea más difícil demostrar por qué no funciona). –
Me siento honrado de leer este proceso de pensamiento. ¡Creo que será mejor que regrese a los libros! –
En este caso, realmente no podemos usar la variable de clase abstracta como argumentos y transmitir su objeto de clase derivado. –