Um colega de trabalho me perguntou hoje como adicionar um intervalo a uma coleção. Ele tem uma classe que herda Collection<T>
. Há uma propriedade get-only desse tipo que já contém alguns itens. Ele deseja adicionar os itens de outra coleção à coleção de propriedades. Como ele pode fazer isso de uma forma amigável com C # 3? (Observe a restrição sobre a propriedade get-only, que impede soluções como fazer Union e reatribuir.)
Claro, um foreach com Property. Adicionar funcionará. Mas um List<T>
AddRange no estilo seria muito mais elegante.
É fácil escrever um método de extensão:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Mas tenho a sensação de que estou reinventando a roda. Não encontrei nada semelhante em System.Linq
ou morelinq .
Design ruim? Basta ligar para adicionar? Perdendo o óbvio?
fonte
ICollection<T>
não parece haver umAdd
método. msdn.microsoft.com/en-us/library/… No entanto,Collection<T>
tem um.Add(T item)
em primeiro lugar? Parece uma abordagem incompleta para oferecer a capacidade de adicionar um único item e então esperar que todos os chamadores iterem para adicionar mais de um de cada vez. Sua afirmação é certamente verdadeira para,IEnumerable<T>
mas me senti frustradoICollections
em mais de uma ocasião. Eu não discordo de você, apenas desabafando.Respostas:
Não, isso parece perfeitamente razoável. Existe um método
List<T>.
AddRange () que basicamente faz exatamente isso, mas requer que sua coleção seja concretaList<T>
.fonte
Tente lançar em List no método de extensão antes de executar o loop. Dessa forma, você pode aproveitar o desempenho de List.AddRange.
fonte
as
operador nunca vai jogar. Sedestination
não puder ser convertido,list
será nulo e oelse
bloco será executado.if (destination is List<T> list)
Já que
.NET4.5
se você quiser uma linha, você pode usarSystem.Collections.Generic
ForEach.ou ainda mais curto como
Em termos de desempenho, é o mesmo que para cada loop (açúcar sintático).
Também não tente atribuí-lo como
a causa
ForEach
é nula.Edit: Copiado de comentários, opinião de Lipert sobre ForEach
fonte
ForEach
parece ser definido apenas emList<T>
, nãoCollection
?Lembre-se de que cada
Add
um verificará a capacidade da coleção e a redimensionará sempre que necessário (mais lento). ComAddRange
, a coleção será definida a capacidade e, em seguida, adicionados os itens (mais rápido). Este método de extensão será extremamente lento, mas funcionará.fonte
Aqui está uma versão um pouco mais avançada / pronta para produção:
fonte
destination
é uma lista deShape
uma classe abstrata.source
é uma lista deCircle
uma classe herdada.Todas as classes C5 Generic Collections Library suportam o
AddRange
método. C5 tem uma interface muito mais robusta que realmente expõe todos os recursos de suas implementações subjacentes e é compatível com as interfacesSystem.Collections.Generic
ICollection
eIList
, o que significa queC5
as coleções podem ser facilmente substituídas como a implementação subjacente.fonte
Você pode adicionar seu intervalo IEnumerable a uma lista e definir ICollection = para a lista.
fonte
Ou você pode apenas fazer uma extensão ICollection como esta:
Usá-lo seria como usá-lo em uma lista:
fonte