Lógica e sua aplicação a Collections.Generic e herança
-
02-07-2019 - |
Pergunta
herda tudo, desde objeto. É a base da herança. Tudo pode ser convertido implicitamente a árvore de herança, ou seja.
object me = new Person();
Portanto, seguindo este até à sua conclusão lógica, um grupo de pessoas também seria um grupo de objetos:
List<Person> people = new List<Person>();
people.Add(me);
people.Add(you);
List<object> things = people; // Ooops.
Exceto, que não vai funcionar, as pessoas que projetaram .NET seja esquecido isso, ou há uma razão, e eu não tenho certeza de qual. Pelo menos uma vez eu tenho que correr em uma situação onde isso teria sido útil, mas eu tinha que acabar usando um truque desagradável (subclasse Lista apenas para implementar um operador de conversão).
A questão é esta: existe uma razão para este comportamento? Existe uma solução mais simples para obter o comportamento desejado?
Para o registro, eu acredito que a situação que eu queria que este tipo de comportamento era uma função de impressão genérico que exibida listas de objetos chamando ToString () e formatar as cordas bem.
Solução
OK, todo mundo que usou genéricos no .net deve ter executar para esse em um ponto ou outro.
Sim, intuitivamente ele deve funcionar. Não, na versão atual do compilador C # isso não acontece.
Eric Lippert tem uma boa explicação sobre esta questão (é em onze partes ou alguma coisa e vai dobrar se importa em alguns lugares, mas é bem vale a pena ler). Consulte aqui .
edit:
cavado um outro link relevante, este discute como Java lida com isso. Consulte aqui
Outras dicas
Você pode usar o LINQ para lançá-lo:
IEnumerable<Person> oldList = someIenumarable;
IEnumerable<object> newList = oldlist.Cast<object>()
À primeira vista, isso não faz sentido intuitivo. Mas ele faz. Olhar para este código:
List<Person> people = new List<Person>();
List<object> things = people; // this is not allowed
// ...
Mouse gerald = new Mouse();
things.add(gerald);
Agora, de repente tem um List
de objetos Person
... com um Mouse
dentro dela!
Isso explica por que a atribuição de um objeto do tipo A<T>
a uma variável do tipo A<S>
não é permitido, mesmo se S
é um supertipo de T
.
A solução LINQ é uma boa. Outra solução, uma vez que você estiver usando o tipo de objeto, é passar a lista como IEnumerable (não a versão genérica).
Editar : C # 4 (atualmente beta) suporta um parâmetro de tipo covariant em IEnumerable. Enquanto você não vai ser capaz de atribuir diretamente a um List
Enquanto que o seu tentando, de fato, o fluxo logicamente, a sua realmente uma característica que muitas línguas não suportam nativamente. Isto é o que é chamado co / variância contra, que tem a ver com quando e como os objetos podem ser implicitamente lançado de um lado para nother por um compilador. Felizmente, C # 4.0 trará covariância e contravariance ao C # arena, e tais moldes implícitas como isso deve ser possível.
Para uma explicação detalhada deste, o seguinte vídeo Channel9 deve ser útil:
Com os métodos de extensão LINQ você pode fazer
IEnumerable<object> things = people.Cast<object>();
List<object> things = people.Cast<object>().ToList();
Caso contrário, desde que você está digitando fortemente a lista a conversão implícita não é permitido.