如何一次性移除泛型列表中的所有空元素?

147

在.Net的C#中,是否有一种默认方法可以删除列表中所有为null的元素?

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

假设一些参数是null;我事先无法知道,我想从列表中删除它们,以便列表只包含不为null的参数。

7个回答

283

你可能需要以下内容。

List<EmailParameterClass> parameterList = new List<EmailParameterClass>{param1, param2, param3...};
parameterList.RemoveAll(item => item == null);

4
没错,这和我的回答一样,只是使用了更新的C#3 lambda语法。 - Mark Bell
@Mark:我看到发布的秒数了,真是太接近了(32、33和34)。;) - Lance
1
是的...嗯,你的答案甚至在旧版本中都有效,所以加1!就是这样,哈! ;Þ - Lance
在清理后,我会添加.Cast<T>(),例如.Cast<EmailParameterClass>(),这将更改List<EmailParameterClass?>的类型为List<EmailParameterClass>。 - Eskil Mjelva Saatvedt
使用现代C#版本中的模式匹配可以使lambda更加优美:item => item is null - phoenix

61

我不知道是否有内置的方法,但是您可以使用 LINQ:

parameterList = parameterList.Where(x => x != null).ToList();

13
如果parameterList已经是一个列表,应避免这样做,因为它会不必要地创建一个新副本。在这种情况下,请使用其他人建议的RemoveAll方法。 - Nick
1
如果集合是一个Array,那么这可能是最好的选择。 - Andrew

29
RemoveAll方法应该可以解决问题:
parameterList.RemoveAll(delegate (object o) { return o == null; });

为什么不使用lambda? - Mike de Klerk
16
这是一个四年前的答案。当时C# 3还比较新,我仍然日常使用C# 2。现在lambda语法是推荐使用的方式;然而,这仍然是一个可行的答案,因此我将其保留在这里,以供任何无法使用较新语法的人参考(出于任何原因)。 - Mark Bell
2
我之前不知道lambda语法是后来才出现的。谢谢你的解释!毫无疑问,它是有效的。 - Mike de Klerk

12

OfType() 方法将跳过空值:

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

IList<EmailParameterClass> parameterList_notnull = 
    parameterList.OfType<EmailParameterClass>();

2
从某种程度上说,这是一种不错的方法,但对于那些只认为OfType选择特定类型对象而没有考虑到它不包括null值的开发者来说,这会带来一些意外...所以我有点犹豫是否要将其引入到我的代码中。 - user3638471
1
@BjörnAliGöransson 同意。这是一个有趣的解决方案,但它并不非常“清晰易读”。使用 lambda 的 .RemoveAll 仍然将所有内容保留在单行中,同时使编写它的开发人员试图实现什么变得非常明显。但是,如果有值得的速度优势,则可能会有用。 - MattD
这个解决方案的酷之处在于,它将把泛型参数从T?更改为T。 - Tim Pohlmann

11

还有一种简单而优雅的选择:

parameters.OfType<EmailParameterClass>();

这将删除所有非EmailParameterClass类型的元素,这显然会过滤掉任何类型为null的元素。

以下是一个测试:

class Program
{
    class Test { }

    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
肯定会的,我还为您添加了测试程序以供娱乐。 - Ryan Naccarato
这很棒,特别是在使用可空注释时,因为它不仅过滤了空值,而且将其强制转换为非可空类型(例如 Bitmap?[] 变成了 Bitmap[])。 - Mark A. Donohoe

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

parameterList = parameterList.Where(param => param != null).ToList();

3

简单易用,无需使用 LINQ:

while (parameterList.Remove(null)) {};

那个方法在List类中紧挨着RemoveAll,所以我建议使用它来提高清晰度。如果性能非常关键,那么你可以采用这种方法(虽然我会删除括号并为不知情的开发人员添加注释)。 - Andrew
1
@Andrew:根据MSDN的说法,RemoveAll不接受null。我也测试过了。不过留个评论也是有意义的。 - Tobias Knauss
1
“RemoveAll” 接收了一个 “Predicate”,因此您应该使用 “RemoveAll(x => x == null)” ,就像在已接受的答案和 Mark Bell 的答案中所看到的那样。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接