Em C #, por que um object List não pode ser armazenado em uma variável List

Parece que um object de lista não pode ser armazenado em uma variável de lista em c # e não pode mesmo ser explicitamente convertido dessa maneira.

List sl = new List(); List ol; ol = sl; 

resulta em Não é possível converter implicitamente o tipo System.Collections.Generic.List para System.Collections.Generic.List

E depois…

 List sl = new List(); List ol; ol = (List)sl; 

resulta em Não é possível converter tipo System.Collections.Generic.List para System.Collections.Generic.List

É claro que você pode fazer isso retirando tudo da lista de strings e colocando-a de volta uma de cada vez, mas é uma solução bastante complicada.

    Pense nisso dessa maneira, se você fizesse tal conversão e, em seguida, incluísse um object do tipo Foo na lista, a lista de seqüências de caracteres não seria mais consistente. Se você tivesse que iterar a primeira referência, você receberia uma exceção de conversão de class, porque assim que atingisse a ocorrência de Foo, o Foo não poderia ser convertido em string!

    Como uma nota lateral, eu acho que seria mais significativo se você pode ou não fazer o cast reverso:

     List ol = new List(); List sl; sl = (List)ol; 

    Eu não uso o C # há algum tempo, então não sei se isso é legal, mas esse tipo de conversão é realmente (potencialmente) útil. Neste caso, você está indo de uma class mais geral (object) para uma class mais específica (string) que se estende da class geral. Dessa maneira, se você adicionar à lista de strings, não estará violando a lista de objects.

    Alguém sabe ou pode testar se tal casting é legal em C #?

    Se você estiver usando o .NET 3.5, dê uma olhada no método Enumerable.Cast. É um método de extensão para que você possa chamá-lo diretamente na lista.

     List sl = new List(); IEnumerable ol; ol = sl.Cast(); 

    Não é exatamente o que você pediu, mas deve fazer o truque.

    Edit: Como observado por Zooba, você pode então chamar ol.ToList () para obter uma lista

    Você não pode converter entre tipos genéricos com parâmetros de tipo diferentes. Tipos genéricos especializados não fazem parte da mesma tree de inheritance e, portanto, são tipos não relacionados.

    Para fazer isso pré-NET 3.5:

     List sl = new List(); // Add strings to sl List ol = new List(); foreach(string s in sl) { ol.Add((object)s); // The cast is performed implicitly even if omitted } 

    Usando o Linq:

     var sl = new List(); // Add strings to sl var ol = new List(sl.Cast()); // OR var ol = sl.Cast().ToList(); // OR (note that the cast to object here is required) var ol = sl.Select(s => (object)s).ToList(); 

    A razão é que uma class genérica como List<> é, na maioria dos casos, tratada externamente como uma class normal. por exemplo, quando você diz List() o compilador diz ListString() (que contém strings). [Pessoas técnicas: esta é uma versão extremamente simples do que está acontecendo]

    Conseqüentemente, obviamente, o compilador não pode ser inteligente o suficiente para converter um ListString em um ListObject, lançando os itens de sua coleção interna.

    É por isso que há methods de extensão para IEnumerable como Convert () que permitem que você forneça facilmente a conversão para os itens armazenados em uma coleção, o que poderia ser tão simples quanto converter de um para outro.

    Isso tem muito a ver com a covariância, por exemplo, tipos genéricos são considerados parâmetros e, se os parâmetros não forem resolvidos adequadamente para um tipo mais específico, a operação falhará. A implicação disso é que você realmente não pode converter para um tipo mais geral como object. E como indicado pelo Rex, o object List não irá converter cada object para você.

    Você pode querer experimentar o código ff em vez disso:

     List sl = new List(); //populate sl List ol = new List(sl); 

    ou:

     List ol = new List(); ol.AddRange(sl); 

    ol irá (teoricamente) copiar todo o conteúdo do sl sem problemas.

    Sim, você pode, do .NET 3.5:

     List sl = new List(); List ol = sl.Cast().ToList(); 

    Mike – Eu acredito que a contravariância não é permitida em C #

    Veja Variação de parâmetro de tipo genérico no CLR para mais informações.

    Na verdade, você não tenta colocar nenhum “object” estranho em sua variante “ol” (como List parece permitir) – porque seu código falharia (porque a lista é realmente List e aceitará apenas objects do tipo String. É por isso que você não pode converter sua variável em uma especificação mais geral.

    Em Java, é o contrário, você não tem genéricos e, em vez disso, tudo é Lista de objects em tempo de execução, e você realmente pode inserir qualquer object estranho em sua lista supostamente escrita. Procure por “Genéricos Reificados” para ver uma discussão mais ampla sobre o problema de java …

    Essa covariância em genéricos não é suportada, mas você pode realmente fazer isso com matrizes:

     object[] a = new string[] {"spam", "eggs"}; 

    C # realiza verificações de tempo de execução para impedir que você coloque, digamos, um int em a .

    Aqui está outra solução pré-.NET 3.5 para qualquer IList cujo conteúdo possa ser convertido implicitamente.

     public IList ConvertIList(IList list) where D : B { List newList = new List(); foreach (D item in list) { newList.Add(item); } return newList; } 

    (Baseado no exemplo de Zooba)

    Eu tenho um:

     private List Leerlingen = new List(); 

    E eu ia preenchê-lo com dados coletados em um List O que finalmente funcionou para mim foi este:

     Leerlingen = (List)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast(); 

    .Cast lo para o tipo que você deseja obter um IEnumerable desse tipo, em seguida, typecast o IEnemuerable para a List<> você deseja.

    Mm, graças aos comentários anteriores, encontrei duas maneiras de descobrir. O primeiro é obter a lista de string de elementos e, em seguida, lançá-lo para a lista de objects IEnumerable:

     IEnumerable ob; List st = new List(); ob = st.Cast(); 

    E o segundo é evitar o tipo de object IEnumerable, apenas convertendo a string para o tipo de object e, em seguida, usando a function “toList ()” na mesma sentença:

     List st = new List(); List ob = st.Cast().ToList(); 

    Eu gosto mais do segundo jeito. Eu espero que isso ajude.

     List sl = new List(); List ol; ol = new List(sl);