Как удалить все нулевые элементы внутри общего списка за один раз?

112

Есть ли метод по умолчанию, определенный в .Net для С #, чтобы удалить все элементы в списке, которые есть null?

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

Скажем , некоторые из параметров null; Я не могу знать заранее и хочу удалить их из своего списка, чтобы он содержал только параметры, которые не равны нулю.

pencilCake
источник

Ответы:

225

Возможно, вам понадобится следующее.

List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};
parameterList.RemoveAll(item => item == null);
Копье
источник
4
Да, это то же самое, что и мой ответ, но с использованием более нового синтаксиса лямбда C # 3.
Марк Белл
@Mark: Я видел опубликованные секунды, и они были близки (32, 33 и 34). ;)
Lance
1
Да ... ваш ответ работает даже в старых версиях, так что +1! Так вот, ха! ; Þ
Lance
43

Я не знаю ни одного встроенного метода, но вы могли бы просто использовать linq:

parameterList = parameterList.Where(x => x != null).ToList();
Пол Хайлс
источник
5
Этого следует избегать, если parameterListон уже является списком, так как это создаст новую копию без необходимости. В этом случае используйте RemoveAllметод, предложенный другими.
Ник
Это, вероятно, лучший вариант, если коллекция представляет собой Array.
Эндрю
25

Метод RemoveAll должен помочь:

parameterList.RemoveAll(delegate (object o) { return o == null; });
Марк Белл
источник
Почему бы не использовать лямбду?
Майк де Клерк
12
Это ответ четырехлетней давности. В то время C # 3 был относительно новым, и я все еще использовал C # 2 изо дня в день. Теперь можно использовать лямбда-синтаксис; однако это все еще рабочий ответ, поэтому я оставил его здесь для тех, кто не может использовать новый синтаксис (по какой-либо причине).
Марк Белл
2
Я не знал, что лямбда-синтаксис появился позже. Спасибо за объяснение! Без сомнения, это действительно так.
Майк де Клерк
8

Метод OfType()пропустит нулевые значения:

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

IList<EmailParameterClass> parameterList_notnull = 
    parameterList.OfType<EmailParameterClass>();
user3450075
источник
В каком-то смысле это хороший подход, но он удивляет разработчика, который просто думает, что OfTypeвыбирает объекты определенного типа, не думая, что он не будет включать nullзначения ... Так что я немного устал вводить это в мой собственный код.
@ BjörnAliGöransson Согласен. Это интересное решение, но оно не очень четко "читается". Использование .RemoveAll с лямбдой по-прежнему сохраняет все в одной строке, делая при этом действительно очевидным, чего пытался достичь разработчик, написавший это. Однако это может быть полезно, если есть смысл в увеличении скорости.
MattD
4
List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};

parameterList = parameterList.Where(param => param != null).ToList();
Стив Даннер
источник
2

Легко и без LINQ:

while (parameterList.Remove(null)) {};
Тобиас Кнаусс
источник
Этот метод находится в Listклассе рядом RemoveAll, поэтому для ясности я бы рекомендовал его. Если производительность оказалась решающей, вы можете воспользоваться этим подходом (хотя я бы снял скобки и, вероятно, добавил бы комментарий для неосведомленных разработчиков).
Эндрю
1
@Andrew: согласно MSDN RemoveAll не принимает значение null. Думаю, я тоже это проверял. Однако комментарий имеет смысл.
Тобиас Кнаусс
1
RemoveAllполучил Predicate, поэтому вы должны использовать RemoveAll(x => x == null), как видно из принятого ответа и ответа Марка Белла.
Эндрю
1

Есть еще один простой и элегантный вариант:

parameters.OfType<EmailParameterClass>();

Это удалит все элементы, не относящиеся к типу, EmailParameterClassчто, очевидно, отфильтрует любые элементы типа null.

Вот тест:

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();
    }
}
Райан Наккарато
источник
это сработает? не будут ссылки на элементы по-прежнему с типом EmailParameterClassи будут иметь только значение, равное null?
derHugo
Это определенно будет, и я добавил тестер для вашего развлечения.
Райан Наккарато,