\=============
MISE À JOUR : J'ai utilisé cette réponse comme base pour cet article de blog :
Pourquoi les paramètres ref et out ne permettent-ils pas la variation de type ?
Voir la page du blog pour plus de commentaires sur cette question. Merci pour cette excellente question.
\=============
Supposons que vous ayez des classes Animal
, Mammal
, Reptile
, Giraffe
, Turtle
et Tiger
avec les relations de sous-classement évidentes.
Supposons maintenant que vous ayez une méthode void M(ref Mammal m)
. M
peut à la fois lire et écrire m
.
Peut-on passer une variable de type Animal
à M
?
Non. Cette variable pourrait contenir un Turtle
mais M
supposera qu'il ne contient que des Mammifères. A Turtle
n'est pas un Mammal
.
Conclusion 1 : ref
les paramètres ne peuvent pas être rendus "plus grands". (Il y a plus d'animaux que de mammifères, donc la variable devient "plus grande" car elle peut contenir plus de choses).
Peut-on passer une variable de type Giraffe
à M
?
Non. M
peut écrire à m
et M
pourrait vouloir écrire un Tiger
en m
. Maintenant vous avez mis un Tiger
dans une variable qui est en fait de type Giraffe
.
Conclusion 2 : ref
Les paramètres ne peuvent pas être "réduits".
Considérons maintenant N(out Mammal n)
.
Peut-on passer une variable de type Giraffe
à N
?
Non. N
peut écrire à n
et N
pourrait vouloir écrire un Tiger
.
Conclusion 3 : out
Les paramètres ne peuvent pas être "réduits".
Peut-on passer une variable de type Animal
à N
?
Hmm.
Eh bien, pourquoi pas ? N
ne peut pas lire de n
il ne peut qu'écrire dessus, non ? Vous écrivez un Tiger
à une variable de type Animal
et tu es prêt, n'est-ce pas ?
Faux. La règle n'est pas " N
ne peut écrire que sur n
".
Les règles sont, brièvement :
1) N
doit écrire à n
avant N
revient normalement. (Si N
jets, tous les paris sont ouverts).
2) N
doit écrire quelque chose pour n
avant de lire quelque chose de n
.
Cela permet cette séquence d'événements :
- Déclarer un champ
x
de type Animal
.
- Passez
x
comme un out
pour N
.
-
N
écrit un Tiger
en n
qui est un alias pour x
.
- Sur un autre fil, quelqu'un écrit un
Turtle
en x
.
-
N
tente de lire le contenu de n
et découvre une Turtle
dans ce qu'il pense être une variable de type Mammal
.
Il est clair que nous voulons rendre cela illégal.
Conclusion 4 : out
les paramètres ne peuvent pas être "agrandis".
Conclusion finale : Ni l'un ni l'autre ref
ni out
Les paramètres peuvent varier selon leur type. Faire autrement revient à rompre la sécurité vérifiable des types.
Si ces questions relatives à la théorie des types de base vous intéressent, envisagez la lecture des documents suivants ma série sur le fonctionnement de la covariance et de la contravariance en C# 4.0 .