如何使用Linq使用FirstOrDefault处理NULL对象属性

pyt*_*hon 15 c# linq entity-framework

我真正的应用程序问题看起来如下所示

Employee empl = new Employee(397947, "David", "Redson", 80000);
        employees.Add(empl);
        employees.Add(new Employee(174966, "Alfred", "Swanson", 50000));
        employees.Add(new Employee(848024, "Alima", "Bieyrou", 40000));
        employees.Add(new Employee(number: 397462, fName: "Robert",
                                     lName: "Nants", salary: 30000));


string s = employees.Where(a => a.EmployeeNumber == 20000).FirstOrDefault().FirstName;
Run Code Online (Sandbox Code Playgroud)

当我使用FirstOrDefault时,它在没有匹配记录时抛出错误.如果有匹配的记录,我想返回值,否则它可以为null或空.

Har*_*lse 28

在FirstOrDefault之前选择linq语句中的字符串,然后获取字符串或默认字符串:

string s = employees
    .Where(a => a.EmployeeNumber == 2000)
    .Select(a => a.FirstName)
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

这不会将完整的员工转移到本地,而只转移到FirstName,这是您想要的唯一字段.

  • 嗯,我想知道为什么这个最自然的解决方案完全被忽略了.+1 (5认同)
  • 在大多数情况下,这应该是可接受的答案,更清晰,更短,更少的数据传输. (3认同)

suj*_*lil 27

您无需使用Where,FirstOrDefault在这种情况下,您可以在FirstOrDefault自身内部指定过滤条件.但是如果没有记录条件的话,哪个会给你null(因为没有第一个值它会给你默认值,对于引用类型对象,默认值是null),你应该null在访问值之前检查,这将抛出NullReferenceException.所以使用这样:

var Employee=employees.FirstOrDefault(a => a.EmployeeNumber == 20000);
if(Employee!=null)
{
  string employee_name=Employee.FirstName;
  // code here
}
Run Code Online (Sandbox Code Playgroud)

或者你可以?.用来检查null这样:

string employee_name = employees.FirstOrDefault(a => a.EmployeeNumber == 20000)?.FirstName;
Run Code Online (Sandbox Code Playgroud)

  • 可查询(LINQ-to-SQL 或 LINQ-to-Entities)集合中不允许使用 null 传播运算符“?.”(又名 Elvis 运算符)。但是,它对于 LINQ-to-Objects 集合工作得很好。 (5认同)
  • 这种方法效率不高。FirstOrDefault 将完整的 Employee 检索到本地,然后丢弃大部分字段。使用 SQL Server Profiler 检查 SQL 语句。 (3认同)

Has*_*thi 9

C# 8和稍后使用null-coalescing运算符??和空检查运算符?

像这样:

string s = employees?.Where(a => a.EmployeeNumber == 20000)
                     .FirstOrDefault()?
                     .FirstName ?? string.Empty;
Run Code Online (Sandbox Code Playgroud)

避免employees列表和任何员工属性中出现任何空异常。


Ash*_*Ash 5

也许您可以尝试使用空传播来简化它:

string s = employees.Where(a => a.EmployeeNumber == 20000).FirstOrDefault()?.FirstName;
Run Code Online (Sandbox Code Playgroud)

  • 正如我之前评论的,这在可查询(LINQ-to-SQL 或 LINQ-to-Entities)集合中是不允许的,因为运算符未转换。@Ivan Stoev 我们确实在其他答案中提到了 C# 版本,其中早期版本中未实现某种行为。通常会提到只有某些版本支持所讨论的操作。 (4认同)
  • 值得一提的是,空传播运算符仅适用于C#6+ (3认同)
  • @fubo C#6是C#的“当前”版本,我不明白为什么我们需要提到这一点。对于其他C#版本,我们不这样做。 (3认同)

gre*_*k40 5

您可以DefaultIfEmpty使用 考虑以下示例:

var entries = new Employee[0];
var result = entries.DefaultIfEmpty(new Employee() { FirstName = "<default name>" }).First().FirstName;
Run Code Online (Sandbox Code Playgroud)