RemoveAll最快最安全,直接修改原列表且语义清晰,适用于可变List;Where+ToList适合链式处理但会新建对象;值类型用HasValue更明确;字符串清理应优先用string.IsNullOrWhiteSpace。

用 RemoveAll 最快最安全
直接改原列表、不新建对象、语义清晰,是生产环境首选。它内部遍历一次,就地移除所有匹配项,比 Where + ToList 少一次内存分配。
-
list.RemoveAll(x => x == null)适用于引用类型(如string、自定义类) - 值类型(如
int?)要用x == null或!x.HasValue,不能用x is null(C# 7.0+ 虽支持,但RemoveAll的泛型约束可能报错) - 如果
list是只读或来自 LINQ 查询(如AsEnumerable().ToList()),RemoveAll会抛NotSupportedException—— 先确认它是可变的List
Where + ToList 适合链式处理
当你已经写了一串 LINQ 操作(比如先 Where 过滤业务逻辑,再剔除 null),用 Where(x => x != null) 接续最自然。但它会新建列表,对大集合有 GC 压力。
- 注意:如果原始
list是List,list.Where(x => x != null).ToList()返回的是新对象,原列表没变 - 别写成
list.Where(x => x != null).ToArray()再转回List—— 多一次拷贝,没意义 - 在 foreach 中边遍历边调用
Where是常见误操作:循环里反复创建新列表,性能雪崩
值类型用 HasValue 别用 == null
对可空值类型(int?、DateTime? 等),== null 编译通过但语义模糊;.HasValue 更明确,且避免某些泛型上下文里的装箱问题。
-
list.RemoveAll(x => !x.HasValue)—— 清理List -
list.Where(x => x.HasValue)—— 链式时同理 - 混用引用/值类型时(比如
object列表),统一用x == null || (x is ValueType && x.Equals(default))太重,建议拆分处理
小心 string.Empty 和 " " 不是 null
业务上常说的“无效数据”往往不止 null,还包括空字符串、全空格字符串。单纯删 null 很可能漏掉真实脏数据。
- 清理字符串建议:
list.RemoveAll(x => string.IsNullOrWhiteSpace(x)) - 注意
string.IsNullOrEmpty不检查空白符,IsNullOrWhiteSpace才是实际常用场景 - 如果列表含多种类型(如
object),先as string再判空,否则IsNullOrWhiteSpace(null)会抛NullReferenceException
实际项目里,null 值常和空字符串、默认值混在一起出现。光盯着 null 去,容易上线后才发现接口返回一堆 "" 或 " ",前端渲染异常。判断逻辑得按业务含义来定,不是语法上“能删就删”。











