简体   繁体   English

如何使用 LINQ 正确处理 null 值和“where”

[英]How do I properly deal with null values and 'where' using LINQ

So I'm in a sticky situation where I have a collection of items of a certain model. For simplicity sake I've made a small model named CarModel .所以我处于一个棘手的情况,我有一个 model 的项目集合。为了简单起见,我做了一个名为CarModel In the collection it will have x amount of CarModel where some of the objects have properties where the value is null.在集合中,它将有 x 数量的CarModel ,其中一些对象具有值为 null 的属性。

As for right now, it will run the where LINQ statement just fine on the first 3 items because they are null because it can check whether null == null .. However, it can't check whether "Test" == null , hence why I'm currently getting the exception至于现在,它将在前 3 个项目上运行where LINQ 语句,因为它们是 null 因为它可以检查是否null == null ..但是,它无法检查是否"Test" == null ,因此为什么我目前得到例外

System.ArgumentNullException: 'Value cannot be null. Parameter name: value' System.ArgumentNullException:“值不能为 null。参数名称:值”

on this line cars.Where(x => x.Name?.ToLower().Contains(car.Name?.ToLower()) == true).ToList();在这条线上cars.Where(x => x.Name?.ToLower().Contains(car.Name?.ToLower()) == true).ToList();

I was thinking about making the Name property nullable to test if that would work but I'm tied to .NET Framework 4.0 and I'm not allowed to change it so I can't use nullable properties because that required C# 8.0 and the language version is tied to the framework so I'm on C# 7.3我正在考虑使Name属性可为 null 以测试它是否可行,但我绑定到.NET Framework 4.0并且我不允许更改它所以我不能使用可为 null 的属性,因为这需要 C# 8.0 和语言版本绑定到框架,所以我在 C# 7.3

using System.Collections.Generic;
using System.Linq;
using System;

class Program
{
    static void Main(string[] args)
    {
        var car = new CarModel();
        car.Name = null;
        
        var cars = new List<CarModel>();
        for (int i = 0; i < 3; i++)
        {
            cars.Add(new CarModel { Name = null });
        }

        for (int i = 0; i < 3; i++)
        {
            cars.Add(new CarModel { Name = "Test" });
        }

        var t = cars.Where(x => x.Name?.ToLower().Contains(car.Name?.ToLower()) == true).ToList();
    }
}

internal class CarModel
{
    public string Name { get; set; }

    public int Year { get; set; }
}

How do I properly filter if some properties might be null at times.如果某些属性有时可能是 null,我该如何正确过滤。 The goal right there is to return a collection of 3 items that it found because it matches the conditions in the WHERE statement.那里的目标是返回它找到的 3 个项目的集合,因为它符合 WHERE 语句中的条件。

In the provided example car.Name is always null , but I assume that you've got an actual use case where that's not always true.在提供的示例中, car.Name始终为null ,但我假设您有一个实际用例,但情况并非总是如此。

The exception you're getting is from the Contains method, which can't handle a null parameter.您得到的异常来自Contains方法,该方法无法处理null参数。 You'll need to add a check for that, either skipping the entire section (not shown) that deals with the matching list or initialize an empty list when car.Name is null. Something like:您需要为此添加一个检查,要么跳过处理匹配列表的整个部分(未显示),要么在car.Name为 null 时初始化一个空列表。类似于:

var t = car.Name is null ? new List<CarModel>() : 
    cars.Where
    (
        x => x.Name?.Contains(car.Name, StringComparison.InvariantCultureIgnoreCase) == true
    ).ToList();

That's assuming that you don't want to match null with null (as Yong Shun's answer does).这是假设您不想将nullnull匹配(正如 Yong Shun 的回答那样)。

To be honest though, it might make more sense to ensure that your CarModel object doesn't accept null name values.老实说,确保您的CarModel object 不接受null名称值可能更有意义。 Required a name in the constructor, use a property setter that throws on null and so on.在构造函数中需要一个名称,使用一个在null上抛出的属性设置器等等。 Depending on use case, of course.当然,取决于用例。

Just filter out the nulls before using the contains, you can't do a contains on a null value.只需在使用包含之前过滤掉空值,您不能对 null 值执行包含。

var t = cars.Where(x => x.Name != null && x.Name.ToLower().Contains(car.Name)).ToList();

Perhaps you can write the query with dealing with 2 conditions:也许您可以编写处理 2 个条件的查询:

  1. When the input value is null , query Name with null .当输入值为null时,查询Namenull
  2. When the input value is not null , query Name with not null and perform a case-insensitive search.当输入值不是null时,查询Name不是null并进行不区分大小写的搜索。
  3. Conditions 1 & 2 with or (fulfill either one).条件 1 和 2 与or (满足其中一个)。
var t = cars.Where(x => (car.Name == null && x.Name == null)
    || (car.Name != null && x.Name != null && x.Name.ToLower().Contains(car.Name.ToLower()) == true))
    .ToList();

Sample program示例程序

The reason you get the exception error is because Contains method requires non-null argument.您收到异常错误的原因是因为 Contains 方法需要非空参数。

so you should revise your code like below,所以你应该像下面这样修改你的代码,

var t = cars.Where(x => x.Name?.ToLower().Contains(car.Name?.ToLower() ?? string.Empty) == true).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM