ChatGPT解决这个技术问题 Extra ChatGPT

何时使用 .First 以及何时将 .FirstOrDefault 与 LINQ 一起使用?

我四处搜索,并没有真正找到关于何时使用 .First 以及何时将 .FirstOrDefault 与 LINQ 一起使用的明确答案。

您想什么时候使用 .First?仅当您想在没有返回结果的情况下捕获异常时? var 结果 = List.Where(x => x == "foo").First();

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

就此而言,Take 怎么样? var 结果 = List.Where(x => x == "foo").Take(1);

.First.FirstOrDefault 都将谓词作为参数,因此 var result = List.Where(x => x == "foo").First(); 可以重写为 var result = List.First(x => x == "foo");
不要忘记考虑 SingleSingleOrDefault。我讨厌人们在真正的意思是 Single 时使用 First ; )
如果返回多个元素,Single 或 SingleOrDefault 会抛出异常!我认为 FirstOrDefault 在大多数情况下更好!
关键是当您期望 Single 结果时,您应该这样说,并且异常表明您的逻辑失败。
还要考虑使用 .FirstOrDefault() 总是让您有机会抛出更有意义的异常。如果引发了序列异常并且方法中有多个 .First(),则可能难以辨别哪个语句是问题所在。

j
jpaugh

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

当您知道需要检查是否存在元素时,请使用 FirstOrDefault()。换句话说,什么时候序列为空是合法的。您不应该依赖异常处理来进行检查。 (这是不好的做法,可能会损害性能)。

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


我唯一要补充的是,如果您选择的类型的默认值可能是有效值,例如您的结果可能是 int 值 0,那么处理异常似乎是处理此问题的最佳方法.
从头开始,我找到了一种更好的方法来完成它,使用: DefaultIfEmpty(-1).First()
Take 不会只返回一个元素,它最多返回一个元素(当然,如果您指定 1)。如果序列最初为空,它也可能返回 0 个元素。
@RoyiNamir,是的,在要采用的参数为1的问题的上下文中。我还在该句子之后的括号中指出了这一点。
我认为最好先解释一下 Take 的工作原理,然后再解释一下 First()Take(1) 的相同之处
D
DIF

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

Skip()Take() 通常用于在结果中设置分页。 (比如在下一页显示前 10 个结果,接下来的 10 个等)

希望这可以帮助。


A
A. Gladkiy

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

因此,如果您准备好并愿意处理可能出现的异常,.First() 就可以了。如果您更愿意检查 != null 的返回值,那么 .FirstOrDefault() 是您更好的选择。

但我想这也有点个人喜好。使用对您更有意义且更适合您的编码风格的那个。


p
p__d

第一的()

返回序列的第一个元素。当结果中没有元素或源为空时,它会引发错误。你应该使用它,如果需要多个元素并且你只想要第一个元素。

第一或默认()

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

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

https://i.stack.imgur.com/fJntd.png

如何使用 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()


在我看来,声明“应该发生错误”。在第三个 FirstOrDefault() 示例下具有误导性。
m
mmx

首先,Take 是一种完全不同的方法。它返回一个 IEnumerable<T> 而不是一个 T,所以就这样了。

FirstFirstOrDefault 之间,您应该在确定元素存在时使用 First,如果不存在,则说明存在错误。

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


u
user2051770

第一的:

返回序列的第一个元素

抛出异常:结果中没有元素

在以下情况下使用:当预期有多个元素并且您只想要第一个元素时

第一个或默认值:

返回序列的第一个元素,如果没有找到元素,则返回默认值

抛出异常:仅当源为空时

在以下情况下使用:当预期有多个元素并且您只需要第一个元素时。结果也可以为空

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


K
Kye

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

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

这就是为什么我总是使用 FirstOrDefault(),即使我知道空条目会构成异常情况。

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

“不要故意从您自己的源代码中抛出 System.Exception [...]”(source)。考虑引发不同的异常类型(例如 ArgumentException)或定义自定义异常类型(例如 RecordNotFoundException)。
N
Nimesh khatri

第一的()

当您知道结果包含超过 1 个预期的元素并且您应该只使用序列的第一个元素时。

第一或默认()

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


R
Ramazan Binarbasi

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

First/FirstOrDefault Last/LastOrDefault Single/SingleOrDefault

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

  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();


N
NULL

我发现一个网站可以解释 FirstOrDefault
http://thepursuitofalife.com/the-linq-firstordefault-method-and-null-resultsets/
如果查询没有结果,并且您想调用 First() 或 Single() 来获得单行.. . 你会得到一个“序列不包含元素”的异常。

免责声明:我从未使用过 LINQ,所以如果这离题了,我深表歉意。


V
Vasil Kosturski

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


根据您的上下文,.SingleOrDefault() 可能很容易被滥用,并且可能会影响某些类型的查询的性能。 .SingleOrDefault() 的底层实现实际上使用 .Take(2) 然后应用验证逻辑。代码气味更多地在于我们为什么使用 OrDefault(),而不一定是 First vs Single 如果我们的代码已经预先假设或预先验证条件只会返回 1 行或不返回任何行,我们是否需要在方法链的后面继续使用和验证 .Single()
M
Manish Basantani
someList.First(); // exception if collection is empty.
someList.FirstOrDefault(); // first item or default(Type)

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

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

代码:

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

我想看看其他人对此的评论。


引用类型和可空类型的默认值为空。
快速失败是好的 - 但是对于您描述的场景,我宁愿看到首先,让它失败,捕获异常,然后返回一个有意义的错误。像 catch(InvalidOperationException e){throw new InvalidOperationException("一天内不能有零笔交易!", e)};但是,是的,使用默认值来避免处理真正的业务逻辑问题是非常糟糕的。
B
BoltClock

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

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

不完全是。当您只需要检索一个项目或在将结果分配给一个不是数组的值时必须避免编译错误并且您确定查询返回一个结果时,第一个构造函数被广泛使用。虽然使用第二个构造函数而不是使用额外的 .Where() 可能看起来更快(因为您认为 LINQ 在找到第一个后停止评估列表中的项目)它总是停在第一个元素
P
Paolo Forgia

linq 有很多方法可以实现对集合的单个简单查询,只需我们在 sql 中编写连接,可以根据需要和必要性首先或最后应用过滤器。

https://i.stack.imgur.com/a7jGs.png