【问题标题】:All array slots contains last result所有数组槽都包含最后一个结果
【发布时间】:2019-07-11 08:46:31
【问题描述】:

我很确定以前有人问过这个问题,但我不知道要搜索什么:

我想用我在 lambda 表达式中找到的内容填充一个数组。 我这样做

IEnumerable<CapOrderTimeSlot>[] dummyDates = new IEnumerable<CapOrderTimeSlot>[DayCount];

for (int i=0; i< DayCount; i++)
{
    dummyDates[i] = OrderSlots.Where(os => os.ComputedStartDate == FirstDate.AddDays(i));
}

问题是数组中的每个项目最终都包含相同的项目(可能是循环中的最后一个结果)。

如何避免这种情况?

【问题讨论】:

  • propably 循环中的最后一个结果”是什么意思?你怎么能不确定这是否是最后的结果?要么是,要么不是。
  • 你是故意选择IEnumerable的吗?是否打算在每次访问dummyDates 中的元素时执行查询?你打算换OrderSlots吗?这样您就可以在运行时动态地对变化做出反应?

标签: c# arrays linq lambda


【解决方案1】:

问题在于此代码将表达式保存在每个数组元素中,而不是“物化”集合中。同时,由于闭包,所有保存的表达式都“链接”到相同的 i 值。这就是您获得最后一个值的原因。

这样改:

for (int i=0; i< DayCount; i++)
{
    dummyDates[i] = OrderSlots.Where(os => os.ComputedStartDate == FirstDate.AddDays(i)).ToArray();
}

【讨论】:

  • 最后使用 .Single 而不是 ToArray 可能会更好..但这取决于 OP
  • @TonyAbrams 为什么是Single?该帖子显示IEnumerable&lt;CapOrderTimeSlot&gt;[] 它需要一个集合数组
  • @Mong Zhu ...哎呀完全错过了:)
  • 如果后面的 dummyDates 数组被多次遍历,结果将不一样。如果您将表达式留在数组中,它们将被一遍又一遍地执行 - 可能会损害性能并产生一些副作用。
【解决方案2】:

您的循环变量iLinq 方法捕获。尝试将其分配给循环内的局部变量:

IEnumerable<CapOrderTimeSlot>[] dummyDates = new IEnumerable<CapOrderTimeSlot>[DayCount];

for (int i = 0; i < DayCount; i++)
{
    int temp = i;
    dummyDates[i] = OrderSlots.Where(os => os.ComputedStartDate == FirstDate.AddDays(temp));
}

There 是一篇很好的文章来解释这个问题

【讨论】:

  • 这与只使用 i 有何不同?
  • i 变量在 linq 执行后被捕获和评估。如果循环内有局部变量,每次都会对其进行评估
猜你喜欢
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多