Jak za jednym razem usunąć wszystkie puste elementy z ogólnej listy?

112

Czy istnieje domyślna metoda zdefiniowana w .Net dla C #, aby usunąć wszystkie elementy z listy, które są null?

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

Powiedzmy, że niektóre parametry są null; Nie mogę wiedzieć z góry i chcę je usunąć z mojej listy, aby zawierała tylko parametry, które nie są zerowe.

ołówekCake
źródło

Odpowiedzi:

225

Prawdopodobnie będziesz potrzebować następujących.

List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};
parameterList.RemoveAll(item => item == null);
Lanca
źródło
4
Tak, to jest to samo, co moja odpowiedź, ale używam nowszej składni lambda C # 3.
Mark Bell
@Mark: Widziałem opublikowane sekundy i człowieku było blisko (32, 33 i 34). ;)
Lance
1
Tak ... cóż, twoja odpowiedź działa nawet w starszych wersjach, więc +1! No więc, ha! ; Þ
Lance
43

Nie znam żadnej wbudowanej metody, ale możesz po prostu użyć linq:

parameterList = parameterList.Where(x => x != null).ToList();
Paul Hiles
źródło
5
Należy tego unikać, jeśli parameterListjest już Listą, ponieważ spowoduje to niepotrzebne utworzenie nowej kopii. W takim przypadku użyj RemoveAllmetody tak, jak sugerują inni.
Nick
Jest to prawdopodobnie najlepsza opcja, jeśli kolekcja to Array.
Andrew,
25

Metoda RemoveAll powinna załatwić sprawę:

parameterList.RemoveAll(delegate (object o) { return o == null; });
Mark Bell
źródło
Dlaczego nie skorzystać z lambdy?
Mike de Klerk
12
To jest odpowiedź sprzed czterech lat. W tamtym czasie C # 3 był stosunkowo nowy i nadal używałem C # 2 na co dzień. Składnia lambda jest teraz właściwą drogą; jednak jest to nadal działająca odpowiedź, więc zostawiłem ją tutaj dla każdego, kto nie może używać nowszej składni (z jakiegokolwiek powodu).
Mark Bell
2
Nie wiedziałem, że składnia lambda pojawiła się później. Dziękuję za wyjaśnienie! Bez wątpienia jest to ważne.
Mike de Klerk
8

Metoda OfType()pominie wartości null:

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

IList<EmailParameterClass> parameterList_notnull = 
    parameterList.OfType<EmailParameterClass>();
user3450075
źródło
W pewnym sensie jest to dobre podejście, ale zaskakuje dewelopera, który po prostu myśli, że OfTypewybiera obiekty określonego typu, nie myśląc, że nie będzie zawierał nullwartości ... Więc jestem trochę zmęczony wprowadzaniem tego do mojego własnego kodu.
@ BjörnAliGöransson Zgoda. To ciekawe rozwiązanie, ale nie „czyta” zbyt jasno. Używanie .RemoveAll z lambdą nadal utrzymuje wszystko w jednym wierszu, jednocześnie pokazując, co chciał osiągnąć programista, który to napisał. Może to jednak być przydatne, jeśli warto skorzystać z szybkości.
MattD,
4
List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};

parameterList = parameterList.Where(param => param != null).ToList();
Steve Danner
źródło
2

Łatwo i bez LINQ:

while (parameterList.Remove(null)) {};
Tobias Knauss
źródło
Ta metoda jest w Listklasie tuż obok RemoveAll, więc polecam ją dla jasności. Jeśli wydajność okazała się kluczowa, możesz zastosować to podejście (chociaż usunąłbym nawiasy i prawdopodobnie dodałbym komentarz dla nieświadomych programistów).
Andrew,
1
@Andrew: zgodnie z MSDN RemoveAll nie przyjmuje wartości null. Myślę, że też to przetestowałem. Komentarz ma jednak sens.
Tobias Knauss,
1
RemoveAllotrzymała Predicate, więc powinieneś użyć RemoveAll(x => x == null), jak widać w zaakceptowanej odpowiedzi Marka Bella.
Andrew,
1

Jest jeszcze jedna prosta i elegancka opcja:

parameters.OfType<EmailParameterClass>();

Spowoduje to usunięcie wszystkich elementów, które nie są typu, EmailParameterClassco oczywiście odfiltruje wszelkie elementy typu null.

Oto test:

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
źródło
Czy to zadziała? nie będzie odwołaniami do elementu nadal typu EmailParameterClassi będzie mieć tylko wartość równą null?
derHugo
Na pewno tak i dodałem tester dla twojej rozrywki.
Ryan Naccarato