Como remover todos os elementos nulos de uma lista genérica de uma vez?

112

Existe um método padrão definido em .Net for C # para remover todos os elementos de uma lista quais são null?

List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};

Digamos que alguns dos parâmetros sejam null; Não posso saber com antecedência e quero removê-los da minha lista para que ela contenha apenas parâmetros que não sejam nulos.

pencilCake
fonte

Respostas:

225

Você provavelmente vai querer o seguinte.

List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};
parameterList.RemoveAll(item => item == null);
Lança
fonte
4
Sim, é igual à minha resposta, mas usando a sintaxe lambda mais recente do C # 3.
Mark Bell
@Mark: Eu vi os segundos postados e cara, estava perto (32, 33 e 34). ;)
Lance de
1
Sim ... bem, sua resposta funciona mesmo em versões mais antigas, então +1! Então aí, ha! ; Þ
Lance de
43

Não conheço nenhum método embutido, mas você poderia apenas usar o linq:

parameterList = parameterList.Where(x => x != null).ToList();
Paul Hiles
fonte
5
Isso deve ser evitado se parameterListjá for uma Lista, pois criará desnecessariamente uma nova cópia. Nesse caso, use o RemoveAllmétodo como outros sugerem.
Nick
Esta é provavelmente a melhor opção se a coleção for uma Array.
Andrew
25

O método RemoveAll deve resolver o problema:

parameterList.RemoveAll(delegate (object o) { return o == null; });
Mark Bell
fonte
Por que não usar o lambda?
Mike de Klerk
12
Esta é uma resposta de quatro anos. Na época, o C # 3 era relativamente novo e eu ainda estava usando o C # 2 no dia-a-dia. A sintaxe lambda agora é o caminho a percorrer; no entanto, esta ainda é uma resposta funcional, então deixei aqui para qualquer pessoa que não consiga usar a sintaxe mais recente (por qualquer motivo).
Mark Bell
2
Eu não sabia que a sintaxe lambda veio depois. Obrigado pela sua explicação! Sem dúvida, é válido.
Mike de Klerk
8

O método OfType()irá ignorar os valores nulos:

List<EmailParameterClass> parameterList =
    new List<EmailParameterClass>{param1, param2, param3...};

IList<EmailParameterClass> parameterList_notnull = 
    parameterList.OfType<EmailParameterClass>();
user3450075
fonte
De certa forma, essa é uma boa abordagem, mas traz uma surpresa para o desenvolvedor que apenas pensa que OfTypeseleciona objetos de um determinado tipo, não achando que não incluirá nullvalores ... Então estou um pouco cansado de apresentar isso em meu próprio código.
@ BjörnAliGöransson Concordo. É uma solução interessante, mas não "lê" muito claramente. Usar .RemoveAll com um lambda ainda mantém tudo em uma única linha enquanto torna realmente óbvio o que o desenvolvedor que o escreveu estava tentando alcançar. No entanto, isso pode ser útil se houver um benefício de velocidade que valha a pena.
MattD
4
List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};

parameterList = parameterList.Where(param => param != null).ToList();
Steve Danner
fonte
2

Fácil e sem LINQ:

while (parameterList.Remove(null)) {};
Tobias Knauss
fonte
Esse método está em Listaula próximo a RemoveAll, então eu recomendo aquele para maior clareza. Se o desempenho for crucial, você pode seguir essa abordagem (embora eu remova os colchetes e provavelmente adicione um comentário para desenvolvedores desatentos).
Andrew
1
@Andrew: de acordo com o MSDN, RemoveAll não leva nulo. Acho que também testei isso. No entanto, um comentário faz sentido.
Tobias Knauss
1
RemoveAllrecebeu um Predicate, então você deve usar RemoveAll(x => x == null), conforme visto na resposta aceita e de Mark Bell.
Andrew
1

Existe outra opção simples e elegante:

parameters.OfType<EmailParameterClass>();

Isso removerá todos os elementos que não são do tipo, o EmailParameterClassque obviamente filtrará quaisquer elementos do tipo null.

Aqui está um teste:

class Test { }
class Program
{
    static void Main(string[] args)
    {
        var list = new List<Test>();
        list.Add(null);
        Console.WriteLine(list.OfType<Test>().Count());// 0
        list.Add(new Test());
        Console.WriteLine(list.OfType<Test>().Count());// 1
        Test test = null;
        list.Add(test);
        Console.WriteLine(list.OfType<Test>().Count());// 1
        Console.ReadKey();
    }
}
Ryan Naccarato
fonte
Isso vai funcionar? não serão as referências de elemento ainda do tipo EmailParameterClasse só terão um valor igual anull ?
derHugo
Definitivamente vai e eu adicionei um testador para o seu entretenimento.
Ryan Naccarato