1

假设我有以下项目列表:

List<Item> items = Item.GetSomeItems();

我想从项目列表中检索具有 id 的特定项目:

int itemID = 2;

以下哪种方式是正确和正确的检索项目的方式?

Item item = items.Find(x => x.ItemID == itemID);

或者

Item item items.Where(x => x.ItemID == itemID).FirstOrDefault();

也许这些都不是使用 LINQ 的最佳解决方案。无论哪种方式,对最佳方法的解释都会有所帮助,因为我经常检索单个业务对象项。何时使用哪个功能也很棒。谢谢你。

4

3 回答 3

4

我不知道Find()和之间的实现差异是什么Where()。虽然我怀疑它们是相同的巧合,但我建议坚持使用 LINQ 扩展方法(Where()Single[OrDefault]())而不是特定于您选择的集合实现的方法。因为它们是扩展方法,所以IEnumerable<T>如果您愿意,您可以更灵活地选择不同的集合实现。

对于奖励积分:

不过,这里有几件事让我担心——你从某个地方加载东西,然后在内存中过滤它们。我希望看到更类似于:

Item item = Item.GetItemForId(2);

这将过滤留给(大概)数据库。尽管这可能违反了 SRP,但实际上您正在前往:

IRepository<Item> repository = this.itemRepository;
Item item = repository.Get(2);

如果您使用完整的 Linq to SQL/Entities,您将能够利用延迟执行并执行以下操作:

Item item = context.Items.SingleOrDefault(i => i.Id == 2);

这不会在调用之前加载所有项目SingleOrDefault(),而是会查看 who 表达式并为其生成适当的 SQL,例如:

SELECT [fields] FROM Item WHERE Id = @id

这都是我的假设,但我确实想明确指出,Linq to Entities(实体框架)Linq to SQL之间存在很大差异,后者构建 SQL 语句以发送到数据库,而Linq to Objects是相同的方法调用,但在内存中的集合对象上工作。

于 2012-05-24T15:29:08.890 回答
3

.FirstOrDefault()如果您希望集合中存在指定的值并且这不是例外情况,那么使用第二种情况肯定更好。

另请注意,它Find()是 的一种方法List<T>,而是Where()一种扩展方法,它可以应用于任何实现了 的类型IEnumerable<T>,因此通过在您的代码中使用,Where()您可以获得更大的灵活性。

于 2012-05-24T15:25:40.067 回答
3

您应该使用以下内容:

Item item = items.FirstOrDefault(x => x.ItemID == itemID);

根据您希望它的工作方式,在 Single、SingleOrDefault、First 和 FirstOrDefault 之间选择作为要使用的 LINQ 方法。如果列表中的多个项目与查询匹配,Single 将引发错误,First 将简单地返回它遇到的第一个与查询匹配的项目。如果没有 OrDefault,如果找不到匹配项,它们将抛出错误,在这种情况下它将返回 null。这比尝试使用 null 并获得 null 引用异常要好。

因此,例如,如果您只想处理只有一个项目与 ItemID 匹配的情况,请使用 Single。如果有多个不是无效的,并且您想优雅地处理没有匹配项,请使用 FirstOrDefault 并在使用它之前检查结果项是否为空。

于 2012-05-24T15:29:41.977 回答