何时使用.First以及何时将.FirstOrDefault与LINQ结合使用?


824

我到处搜索,但对于要.First何时使用.FirstOrDefaultLINQ 和何时要使用LINQ 并没有真正找到明确的答案。

  • 您什么时候要使用.First?仅当您希望在没有返回结果的情况下捕获异常时?

    var result = List.Where(x => x == "foo").First();
  • 您什么时候要使用.FirstOrDefault?如果没有结果,何时总是需要默认类型?

    var result = List.Where(x => x == "foo").FirstOrDefault();
  • 那么,Take呢?

    var result = List.Where(x => x == "foo").Take(1);

86
.First并且.FirstOrDefault都接受谓词作为参数,所以var result = List.Where(x => x == "foo").First();可以改写为var result = List.First(x => x == "foo");
日安Schmits

59
不要忘记考虑SingleSingleOrDefault。我讨厌人们用First真心的话Single; )
BartoszKP 2013年

19
如果返回多个元素,Single或SingleOrDefault将引发异常!我认为FirstOrDefault在大多数情况下会更好!
埃里克·德雷文

21
关键是当您期望获得“单一”结果时,应该这样说,并且异常表明您的逻辑失败。
NetMage

1
还应考虑使用.FirstOrDefault()Always(总是)使您有机会引发更有意义的异常。如果抛出了一个序列异常,并且.First()在一个方法中抛出了多个异常,则可能很难分辨出哪个语句是问题所在。
StingyJack

Answers:


807

First()当我知道或期望序列具有至少一个元素时,我会使用。换句话说,当序列异常为空时,则为空。

使用FirstOrDefault()时,你知道你需要检查是否有一个元素或没有。换句话说,在合法的情况下,序列为空。您不应依赖异常处理来进行检查。(这是不好的做法,可能会损害性能)。

最后,和之间的区别在于First()Take(1)First()返回元素本身,而Take(1)返回的元素序列只包含一个元素。


4
@driis-我想我们可以在First和FirstOrDefault之间选择时使用异常例外准则的口头禅。感谢您的明确答复。
大都会蓝精灵

5
我唯一要添加的是,如果您选择的类型的默认值可能是有效值,例如您的结果可能是int值0,那么处理异常似乎是处理此问题的最佳方法。
PeterBelm 2012年

25
从头开始,我发现了一种更好的实现方法,请使用:DefaultIfEmpty(-1).First()
PeterBelm 2012年

5
Take不能完全返回一个元素,它最多返回一个元素(当然,如果您指定1)。如果序列最初为空,则它也可能返回0个元素。
SPIRiT_1984

3
@RoyiNamir,是的,在要采用的参数为1的问题中,我也注意到该句子后面的括号内。
driis

272

.First没有结果时将抛出异常。.FirstOrDefault不会,它只会返回null(引用类型)或值类型的默认值。(例如,0对于int。)这里的问题不是当您想要默认类型时,而是更多:您是否愿意处理异常或处理默认值?由于异常应该是例外,FirstOrDefault因此在不确定是否要从查询中获取结果时,首选使用。当逻辑上数据应该存在时,可以考虑异常处理。

Skip()并且Take()通常在设置结果分页时使用。(例如,显示前10个结果,以及下一页上的后10个结果,等等)

希望这可以帮助。


5
@Jeroen-有关使用“跳过/获取”的更好用例的要点。
蓝精灵”地铁

4
+1用于解释,.FirstOrDefault对于引用类型将返回null。我对什么是“默认”对象感到困惑。这个答案清除了这一点。
Mike Taverne

115

.First()如果没有要返回的行,将抛出异常,而.FirstOrDefault()将返回默认值(NULL对于所有引用类型)。

因此,如果您准备好并愿意处理可能的异常,那就.First()很好。如果您!= null仍然希望检查返回值,那.FirstOrDefault()是更好的选择。

但是我想这也是个人喜好。使用对您更有意义的代码,更好地适合您的编码风格。


66

第一()

  1. 返回序列的第一个元素。
  2. 当结果中没有元素或源为null时,它将引发错误。
  3. 如果需要多个元素,并且只需要第一个元素,则应使用它。

FirstOrDefault()

  1. 返回序列的第一个元素,如果找不到元素,则返回默认值。
  2. 仅当源为null时,它才会引发错误。
  3. 如果需要多个元素,并且只需要第一个元素,则应使用它。如果结果为空也很好。

我们有一个UserInfos表,其中包含一些记录,如下所示。根据下表,我创建了示例...

用户信息表

如何使用First()

var result = dc.UserInfos.First(x => x.ID == 1);

只有一条记录,其中ID ==1。应返回该记录
ID:1名:Manish姓:Dubey电子邮件:xyz@xyz.com

var result = dc.UserInfos.First(x => x.FName == "Rahul");   

有多个记录,其中FName ==“ Rahul”。第一条记录应该返回。
ID:7名:Rahul姓:Sharma电子邮件:xyz1@xyz.com

var result = dc.UserInfos.First(x => x.ID ==13);

没有ID == 13的记录。应该发生错误。
InvalidOperationException:序列不包含任何元素

如何使用FirstOrDefault()

var result = dc.UserInfos.FirstOrDefault(x => x.ID == 1);

只有一条记录,其中ID ==1。应返回该记录
ID:1名:Manish姓:Dubey电子邮件:xyz@xyz.com

var result = dc.UserInfos.FirstOrDefault(x => x.FName == "Rahul");

有多个记录,其中FName ==“ Rahul”。第一条记录应该返回。
ID:7名:Rahul姓:Sharma电子邮件:xyz1@xyz.com

var result = dc.UserInfos.FirstOrDefault(x => x.ID ==13);

没有ID == 13的记录。返回值为null

希望它可以帮助您了解何时使用First()FirstOrDefault()


4
我认为语句“应该发生错误”。在第三个FirstOrDefault()示例下是令人误解的。
Jannik

您好,您解释得很好,但是当我从联接中获取数据时以及当时使用的是哪个外键表中没有ID时,我有些困惑。目前,我正在使用First(),但在阅读您的回答后,我不知道。请帮忙
Brijesh Mavani

20

首先,Take是一种完全不同的方法。它返回,IEnumerable<T>而不是单个T,因此就可以了。

First和之间FirstOrDefaultFirst如果您确定某个元素存在,则应使用该元素;如果不存在,则将出现错误。

顺便说一句,如果您的序列包含default(T)元素(例如null),并且您需要区分为空和第一个元素为null,则不能使用FirstOrDefault


2
@Mehrdad-要点,回复:.First返回IEnumerable,何时不使用FirstOrDefault。
Metro Smurf

15

第一:

  • 返回序列的第一个元素
  • 引发异常:结果中没有元素
  • 在以下情况下使用:当预期有多个元素并且只需要第一个元素时

FirstOrDefault:

  • 返回序列的第一个元素,如果找不到元素,则返回默认值
  • 引发异常:仅当源为null时
  • 在以下情况下使用:当预期有多个元素并且只需要第一个元素时。也可以将结果为空

来自:http : //www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/


10

另一个需要注意的区别是,如果要在生产环境中调试应用程序,则可能无法访问行号,因此.First()很难确定方法中哪个特定的语句引发了异常。

异常消息也将不包含您可能使用过的任何Lambda表达式,这些表达式甚至会更难调试。

这就是为什么FirstOrDefault()即使我知道null条目都会构成例外情况,我还是始终使用的原因。

var customer = context.Customers.FirstOrDefault(i => i.Id == customerId);
if (customer == null)
{
   throw new Exception(string.Format("Can't find customer {0}.", customerId));
}

5

第一()

当您知道该结果包含多个期望的元素时,您应该只选择序列的第一个元素。

FirstOrDefault()

FirstOrDefault()类似于First(),不同之处在于,如果没有元素与指定条件匹配,则它返回通用集合的基础类型的默认值。如果未找到任何元素,则不会引发InvalidOperationException。但是元素或序列的集合为空,因为它引发异常。


您好,您解释得很好,但是当我从联接中获取数据时以及当时使用的是哪个外键表中没有ID时,我有些困惑。目前,我正在使用First(),但在阅读您的回答后,我不知道。请帮忙
Brijesh Mavani

4

此类型的函数属于元素运算符。下面定义了一些有用的元素运算符。

  1. First / FirstOrDefault
  2. 最后/最后或默认
  3. 单/单或默认

当我们需要根据特定条件从序列中选择单个元素时,可以使用元素运算符。这是一个例子。

  List<int> items = new List<int>() { 8, 5, 2, 4, 2, 6, 9, 2, 10 };

满足条件后,First()运算符返回序列的第一个元素。如果未找到任何元素,则将引发异常。

int result = items.Where(item => item == 2).First();

满足条件后,FirstOrDefault()运算符返回序列的第一个元素。如果未找到任何元素,则它将返回该类型的默认值。

int result1 = items.Where(item => item == 2).FirstOrDefault();


用一个易于理解的例子很好地解释了。
Arslan Bhatti


2
someList.First(); // exception if collection is empty.
someList.FirstOrDefault(); // first item or default(Type)

使用哪一个?它应该由业务逻辑来决定,而不是由对异常/程序失败的担心来决定。

例如,如果业务逻辑说我们在任何工作日都不能有零笔交易(假设)。然后,您不应尝试通过一些智能编程来处理这种情况。我将始终在此类集合上使用First(),并且如果其他事情搞砸了业务逻辑,则让程序失败。

码:

var transactionsOnWorkingDay = GetTransactionOnLatestWorkingDay();
var justNeedOneToProcess = transactionsOnWorkingDay.First(): //Not FirstOrDefault()

我希望看到其他人对此发表评论。


引用和可为null的类型的默认值为null。
dsa

快速失败是有好处的-但是对于您所描述的场景,我宁愿先查看一下,让它失败,捕获异常,然后返回有意义的错误。像catch(InvalidOperationException e){抛出新的InvalidOperationException(“一天不能有零笔交易!”,e)}; 但是,是的,使用默认值避免处理实际的业务逻辑问题是非常糟糕的。
Mathieson 2014年

1

好吧,让我给我两美分。First / Firstordefault用于使用第二个构造函数的情况。我不会解释它是什么,但是这是因为您不想引起异常而可能总是使用一个。

person = tmp.FirstOrDefault(new Func<Person, bool>((p) =>
{
    return string.IsNullOrEmpty(p.Relationship);
}));

不完全是。当您只需要检索一个项目或在将结果分配给不是数组的值时必须避免编译错误时,第一个构造函数被广泛使用,并且您可以确保查询恰好返回一个结果。虽然它可能看起来更快地使用第二个构造函数,而不是使用附加。凡()(因为你认为 LINQ找到停止后的第一次评估列表中的项目),它总是停在第一个元素
USR-本地ΕΨΗΕΛΩΝ

0

其他人已经很好地描述了First()和之间的区别FirstOrDefault()。我想进一步解释这些方法的语义。我认为FirstOrDefault这被滥用了很多。在大多数情况下,当您过滤数据时,您要么期望返回匹配逻辑条件的元素集合,要么期望通过其唯一标识符(例如,用户,书籍,帖子等)来获得单个唯一元素。为什么我们甚至可以说那FirstOrDefault()是代码的味道,不是因为它有什么问题,而是因为它使用得太频繁了。这篇博客文章详细探讨了该主题。IMO大部分时间SingleOrDefault() 是一个更好的选择,因此请小心此错误,并确保您使用最能清楚地代表您的合同和期望的方法。


-6

linq有多种方法可以对集合实施单个简单查询,仅我们在sql中编写联接,便可以根据需要和必要性首先应用过滤器。

这是一个示例,其中我们可以在集合中找到具有id的元素。要对此进行更多补充FirstOrDefault,理想情况下,当集合具有至少一个记录时,方法First,会返回相同的结果。但是,如果集合可以为空。然后First将返回异常,但FirstOrDefault将返回null或默认值。例如,int将返回0。因此,虽然说这种用法是个人喜好,但最好FirstOrDefault避免使用异常处理。 这是一个示例,其中我们遍历了transactionlist的集合

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.