【问题标题】:Return an empty collection when Linq where returns nothing当 Linq 什么都不返回时返回一个空集合
【发布时间】:2009-11-30 22:10:24
【问题描述】:

我使用以下语句的目的是从MachineList 集合(IEnumerable 类型)中获取所有具有iMachineStatus 的机器对象。 MachineList 集合并不总是包含状态为 i 的机器。

当没有机器有MachineStatusi 时,我想返回一个空集合。我对ActiveMachines(首先使用)的调用有效,但InactiveMachines 无效。

public IEnumerable<Machine> ActiveMachines
{
    get
    {
        return Customer.MachineList
            .Where(m => m.MachineStatus == "a");
    }
}

public IEnumerable<Machine> InactiveMachines
{
    get
    {
        return Customer.MachineList
            .Where(m => m.MachineStatus == "i");
    }
}

编辑

经过进一步检查,MachineList 的任何枚举似乎都会导致MachineList 的后续枚举抛出异常:Object reference not set to an instance of an object

因此,调用ActiveMachinesInactiveMachines 并不重要,因为这是MachineList 集合的问题。这尤其令人不安,因为我可以通过在代码中调用之前在 Watch 中枚举它来中断对MachineList 的调用。在其最低级别MachineList 实现NHibernate.IQuery 作为IEnumerable 返回。是什么导致MachineList 在初始枚举后丢失其内容?

【问题讨论】:

  • 不,枚举时没有什么特别的事情发生;看看调试器中有什么“非活动”等会很有趣。我还想知道(例如)MachineStatus 是否是引发异常的外观属性 - 即 public string MachineStatus { get {return someInnerField.Status;}}someInnerFieldnull
  • 真正的问题是您要多次枚举IEnumerable。当您使用 IEnumerable 时,您同意的隐含合同是仅枚举一次!所以真正的答案不是让您的同事更改他的代码以允许多次枚举,而是让您在某个时候执行Customer.MachineList.ToList(),然后只使用结果列表(或者,再次获得一个新的IEnumerable) .您可以进行惰性评估;你可以缓存它,但不要枚举它两次。您也可以公开IQueryable 并多次调用它。

标签: c# linq lambda ienumerable


【解决方案1】:

Where 如果没有匹配则返回一个空序列;这是一个完全有效的序列(非空)。获得空值的唯一方法是调用FirstOrDefaultSingleOrDefault

您确定错误在您认为的位置吗?

int?[] nums = { 1, 3, 5 };
var qry = nums.Where(i => i % 2 == 0);
Console.WriteLine(qry == null); // false
Console.WriteLine(qry.Count()); // 0
var list = qry.ToList();
Console.WriteLine(list.Count); // 0
var first = qry.FirstOrDefault();
Console.WriteLine(first == null); // true

【讨论】:

  • 我就是这么想的。我修改了我的问题以反映引发相同错误的修改。
  • 在我的问题中添加了一些附加信息,这些信息可能有助于了解正在发生的事情。也就是说,我想我可能需要打开一个新线程。
  • 错误必须与 MachineList 的构建方式有关。我一直在从另一个开发人员那里使用这种方法,并且没有检查它的构建方式。感谢您通过询问我是否确定自己在正确的地方寻找正确的方向。
【解决方案2】:

默认情况下,Enumerable.Where 已经返回一个空的IEnumerable&lt;T&gt;,而不是 null。如果您看到“对象引用未设置为对象的实例”。例外,很可能是其他问题。

MachineList 是否为空?如果你没有创建它,你会在调用 .Where(...) 时得到该异常

【讨论】:

  • 感谢您通过询问我是否确定我在正确的地方寻找正确的方向。
【解决方案3】:

此外,如果您希望显式返回一个空集合,这会有所帮助...

Enumerable.Empty<Machine>();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    相关资源
    最近更新 更多