A variação será suportada apenas de forma segura - na verdade, usando as habilidades que o CLR já possui. Portanto, os exemplos que dou no livro de tentar usar um List<Banana>
como List<Fruit>
(ou seja o que for) ainda não funcionarão - mas alguns outros cenários funcionarão.
Em primeiro lugar, ele só terá suporte para interfaces e delegados.
Em segundo lugar, requer que o autor da interface / delegado decore os parâmetros de tipo como in
(para contravariância) ou out
(para covariância). O exemplo mais óbvio é IEnumerable<T>
aquele que só permite que você retire valores "fora" dele - não permite que você adicione novos. Isso vai se tornar IEnumerable<out T>
. Isso não prejudica a segurança de tipo, mas permite que você retorne um IEnumerable<string>
de um método declarado para retornar, IEnumerable<object>
por exemplo.
A contravariância é mais difícil de dar exemplos concretos de uso de interfaces, mas é fácil com um delegado. Considere Action<T>
- isso representa apenas um método que recebe um T
parâmetro. Seria bom ser capaz de converter perfeitamente e usar um Action<object>
como um Action<string>
- qualquer método que receba um object
parâmetro funcionará bem quando for apresentado com um string
. Obviamente, C # 2 já tem covariância e contravariância de delegados até certo ponto, mas por meio de uma conversão real de um tipo de delegado para outro (criando uma nova instância) - consulte P141-144 para exemplos. C # 4 tornará isso mais genérico e (acredito) evitará a criação de uma nova instância para a conversão. (Em vez disso, será uma conversão de referência.)
Espero que isso esclareça um pouco - por favor, me avise se não fizer sentido!