Como posso converter IEnumerable<T> em List<T> em C#?
Pergunta
Estou usando o LINQ para consultar um dicionário genérico e depois usar o resultado como fonte de dados para meu ListView (WebForms).
Código simplificado:
Dictionary<Guid, Record> dict = GetAllRecords();
myListView.DataSource = dict.Values.Where(rec => rec.Name == "foo");
myListView.DataBind();
Eu pensei que isso funcionaria, mas na verdade é um System.InvalidOperationException:
ListView com id 'myListView' deve ter uma fonte de dados que implementa ICollection ou pode executar paginação da fonte de dados se AllowPaging for verdadeiro.
Para fazê-lo funcionar, tive que recorrer ao seguinte:
Dictionary<Guid, Record> dict = GetAllRecords();
List<Record> searchResults = new List<Record>();
var matches = dict.Values.Where(rec => rec.Name == "foo");
foreach (Record rec in matches)
searchResults.Add(rec);
myListView.DataSource = searchResults;
myListView.DataBind();
Existe uma pequena pegadinha no primeiro exemplo para fazer funcionar?
(Não tinha certeza do que usar como título da pergunta para esta, sinta-se à vontade para editar para algo mais apropriado)
Solução
Experimente isto:
var matches = dict.Values.Where(rec => rec.Name == "foo").ToList();
Esteja ciente de que isso basicamente criará uma nova lista a partir da coleção Values original e, portanto, quaisquer alterações no seu dicionário não serão refletidas automaticamente no seu controle vinculado.
Outras dicas
Eu tendo a preferir usar a nova sintaxe do Linq:
myListView.DataSource = (
from rec in GetAllRecords().Values
where rec.Name == "foo"
select rec ).ToList();
myListView.DataBind();
Por que você está pegando um dicionário quando não usa a chave?Você está pagando por essa sobrecarga.
Você também pode tentar:
var matches = new List<Record>(dict.Values.Where(rec => rec.Name == "foo"));
Basicamente, coleções genéricas são muito difíceis de converter diretamente, então você realmente não tem escolha a não ser criar um novo objeto.
myListView.DataSource = (List<Record>) dict.Values.Where(rec => rec.Name == "foo");
Apenas adicionar conhecimento à próxima frase não recupera nenhum dado do banco de dados.Basta criar a consulta (para isso é do tipo iconsulável).Para iniciar esta consulta você deve adicionar .ToList() ou .First() no final.
dict.Values.Where(rec => rec.Name == "foo")