Não participei do PDC 2008, mas ouvi algumas notícias de que o C # 4.0 foi anunciado para oferecer suporte à covariância e contra-variância genérica. Ou seja, List<string>
pode ser atribuído a List<object>
. Como poderia ser?
No livro C # in Depth de Jon Skeet , é explicado por que os genéricos C # não suportam covariância e contra-variância. É principalmente para escrever código seguro. Agora, o C # 4.0 mudou para suportá-los. Isso traria o caos?
Alguém conhece os detalhes sobre C # 4.0 pode dar alguma explicação?
c#
c#-4.0
covariance
contravariance
generic-variance
Morgan Cheng
fonte
fonte
Respostas:
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>
comoList<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) ouout
(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 tornarIEnumerable<out T>
. Isso não prejudica a segurança de tipo, mas permite que você retorne umIEnumerable<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 umT
parâmetro. Seria bom ser capaz de converter perfeitamente e usar umAction<object>
como umAction<string>
- qualquer método que receba umobject
parâmetro funcionará bem quando for apresentado com umstring
. 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!
fonte
List<Banana>
comoIList<Fruit>
", como disse @Ark-kun? Se sim, como isso é possível, embora o parâmetro de tipo daIList<T>
interface não seja definido como covariante (nãoout T
, mas simplesmenteT
).Não que Jon já não tenha feito a cobertura, mas aqui estão alguns links para blogs e vídeos de Eric Lippert. Ele faz um bom trabalho explicando com exemplos.
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
Os vídeos:
https://www.youtube.com/watch?v=3MQDrKbzvqU
https://www.youtube.com/watch?v=XRIadQaBYlI
https://www.youtube.com/watch?v=St9d2EDZfrg
fonte