¿Cómo eliminar todos los elementos nulos dentro de una lista genérica de una sola vez?

112

¿Existe un método predeterminado definido en .Net para C # para eliminar todos los elementos dentro de una lista que son null?

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

Digamos que algunos de los parámetros son null; No puedo saberlo de antemano y quiero eliminarlos de mi lista para que solo contenga parámetros que no sean nulos.

pastel de lápiz
fuente

Respuestas:

225

Probablemente querrás lo siguiente.

List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};
parameterList.RemoveAll(item => item == null);
lanza
fuente
4
Sí, esta es la misma que mi respuesta pero usando la sintaxis lambda más nueva de C # 3.
Mark Bell
@Mark: Vi los segundos publicados y estaba cerca (32, 33 y 34). ;)
Lance
1
Sí ... bueno, tu respuesta funciona incluso en versiones anteriores, ¡así que +1! Así que ahí, ¡ja! ; Þ
Lance
43

No conozco ningún método incorporado, pero podrías usar linq:

parameterList = parameterList.Where(x => x != null).ToList();
Paul Hiles
fuente
5
Esto debe evitarse si parameterListya es una lista, ya que creará una nueva copia innecesariamente. En ese caso, utilice el RemoveAllmétodo como sugieren otros.
Nick
Esta es probablemente la mejor opción si la colección es Array.
Andrew
25

El método RemoveAll debería hacer el truco:

parameterList.RemoveAll(delegate (object o) { return o == null; });
Mark Bell
fuente
¿Por qué no usar la lambda?
Mike de Klerk
12
Esta es una respuesta de cuatro años. En ese momento, C # 3 era relativamente nuevo, y todavía usaba C # 2 día a día. La sintaxis lambda es ahora el camino a seguir; sin embargo, esta sigue siendo una respuesta funcional, así que la dejé aquí para cualquiera que no pueda usar la sintaxis más nueva (por cualquier motivo).
Mark Bell
2
No sabía que la sintaxis lambda llegó más tarde. ¡Gracias por su explicación! Sin duda es válido.
Mike de Klerk
8

El método OfType()omitirá los valores nulos:

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

IList<EmailParameterClass> parameterList_notnull = 
    parameterList.OfType<EmailParameterClass>();
user3450075
fuente
En cierto modo, este es un buen enfoque, pero sorprende al desarrollador que solo piensa que OfTypeselecciona objetos de cierto tipo, sin pensar que no incluirá nullvalores ... Así que estoy un poco cansado de presentar esto en mi propio código.
@ BjörnAliGöransson De acuerdo. Es una solución interesante, pero no se "lee" con mucha claridad. El uso de .RemoveAll con un lambda aún mantiene todo en una sola línea mientras hace que sea realmente obvio lo que el desarrollador que lo escribió estaba tratando de lograr. Sin embargo, esto podría ser útil si hay un beneficio de velocidad que vale la pena.
MattD
4
List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};

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

Fácil y sin LINQ:

while (parameterList.Remove(null)) {};
Tobias Knauss
fuente
Ese método está en Listclase justo al lado RemoveAll, por lo que lo recomendaría para mayor claridad. Si el rendimiento resultó ser crucial, entonces puede seguir este enfoque (aunque eliminaría los corchetes y probablemente agregaría un comentario para los desarrolladores que no lo saben).
Andrew
1
@Andrew: según MSDN, RemoveAll no toma nulo. Creo que también lo he probado. Sin embargo, un comentario tiene sentido.
Tobias Knauss
1
RemoveAllrecibió un Predicate, por lo que debe usar RemoveAll(x => x == null), como se ve en el aceptado y la respuesta de Mark Bell.
Andrew
1

Existe otra opción sencilla y elegante:

parameters.OfType<EmailParameterClass>();

Esto eliminará todos los elementos que no sean de tipo, EmailParameterClasslo que obviamente filtrará cualquier elemento de tipo null.

He aquí una prueba:

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
fuente
¿esto funcionara? ¿No serán las referencias del elemento todavía de tipo EmailParameterClassy solo tendrán un valor igual a null?
derHugo
Definitivamente lo hará y agregué un probador para su entretenimiento.
Ryan Naccarato