LINQ Single vs First

Ian*_*ink 202 .net linq

LINQ:

当我确定查询将返回单个记录时,使用Single()运算符是否更有效?First()

有区别吗?

Arm*_*est 300

如果您期望单条记录,那么在代码中明确表示总是好的.

我知道其他人已经写过为什么你使用其中一个,但我想我会说明为什么你不应该使用一个,当你的意思是另一个.

注意:在我的代码中,我通常会使用FirstOrDefault(),SingleOrDefault()但这是一个不同的问题.

例如,Customers使用复合键(ID,Lang)以不同语言存储的表:

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();
Run Code Online (Sandbox Code Playgroud)

上面的代码引入了可能的逻辑错误(难以跟踪).它将返回多个记录(假设您有多种语言的客户记录),但它总是只返回第一个...有时可能有效......但不能返回其他语言.这是不可预测的.

因为你的意图是返回单一Customer用途Single();

以下将抛出一个异常(在这种情况下你想要的):

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();
Run Code Online (Sandbox Code Playgroud)

然后,你只需按下额头,然后对自己说......哎呀!我忘记了语言领域!以下是正确的版本:

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();
Run Code Online (Sandbox Code Playgroud)

First() 在以下场景中很有用:

DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();
Run Code Online (Sandbox Code Playgroud)

它将返回一个对象,并且由于您正在使用排序,它将是返回的最新记录.

使用Single()时感觉它应该明确,始终返回1条记录将有助于你避免逻辑错误.

  • Single和First方法都可以使用表达式参数进行过滤,因此Where函数不是必需的.示例:Customer customer = db.Customers.Single(c => c.ID == 5); (72认同)
  • @AgentFire [备份你的陈述](http://stackoverflow.com/questions/21194750/which-is-faster-singlepredicate-or-wherepredicate-single) (9认同)
  • @drzaus - 逻辑上,不,它们都根据谓词过滤要返回的值.但是,我检查了反汇编,并且Where(谓词).Single()在我做的简单情况下有三条额外的指令.所以,虽然我不是IL专家,但看起来customers.Single(谓词)应该更有效率. (8认同)
  • @JoshNoe - 我很好奇,`customers.Where(谓词).Single()``customers.Single(谓词)`之间有区别吗? (5认同)
  • 事实证明,@ JoshNoe完全相反. (4认同)
  • @JoshNoe谢谢Josh.我很想编辑删除`Where`子句的答案,但是将它留在那里的数字增加了一些清晰度,特别是对于那些想知道`Single()`和`First()之间区别的人. (2认同)

Alw*_*mer 67

如果找到符合条件的多条记录,则Single将抛出异常.首先将始终从列表中选择第一条记录.如果查询只返回1条记录,则可以使用First().

InvalidOperationException如果集合为空,则两者都将抛出异常.或者你可以使用SingleOrDefault().如果列表为空,则不会抛出异常

  • “如果查询仅返回 1 条记录,则可以使用 First()” 为什么不使用 Single() 来更好地传达您的意图?另外,如果我们在期待一件物品的时候神奇地得到了多件物品,我们难道不想知道这一点吗?否则我们的程序将在潜在损坏的状态下运行。 (2认同)

Die*_*des 28

单()

返回查询的单个特定元素

使用时:如果恰好有1个元素; 不是0或大于1.如果列表为空或具有多个元素,它将抛出异常"序列包含多个元素"

的SingleOrDefault()

返回查询的单个特定元素,如果未找到结果,则返回默认值

使用时:预期为0或1个元素时.如果列表包含2个或更多项,它将抛出异常.

第一()

返回具有多个结果的查询的第一个元素.

使用时:当需要一个或多个元素时,您只需要第一个元素.如果列表不包含任何元素,它将抛出异常.

FirstOrDefault()

返回包含任意数量元素的列表的第一个元素,如果列表为空,则返回默认值.

使用时:当预期有多个元素且您只想要第一个元素时.或者列表为空,您需要指定类型的默认值,与之相同default(MyObjectType).例如:如果列表类型是list<int>,它将返回列表中的第一个数字,如果列表为空,则返回0.如果是list<string>,它将从列表返回第一个字符串,如果列表为空则返回null.

  • 很好的解释。我只会更改您可以在需要 *1 个或更多元素时使用 `First`,而不仅仅是“多于 1”,以及带有任意数量元素的 `FirstOrDefault`。 (2认同)

And*_*are 18

这两种方法之间存在细微的语义差异.

用于Single从应该包含一个元素但不再包含一个元素的序列中检索第一个(也是唯一的)元素.如果序列具有多于on元素,Single则调用将导致抛出异常,因为您指示应该只有一个元素.

用于First从可包含任意数量元素的序列中检索第一个元素.如果序列具有多于on元素,First则调用不会导致抛出异常,因为您指示只需要序列中的第一个元素而不关心是否存在更多元素.

如果序列不包含任何元素,则两个方法调用都将导致抛出异常,因为两个方法都期望至少存在一个元素.


Pat*_*her 16

如果您不希望在有多个项目的情况下抛出异常,请使用First().

两者都很有效率,拿第一项. First()效率稍高,因为它不会检查是否有第二项.

唯一的区别是Single()期望枚举中只有一个项目开始,并且如果有多个项目将抛出异常.您使用 .Single() ,如果你特别想要抛出的异常在这种情况下.


Eti*_*tel 14

如果我记得,Single()检查第一个元素后面是否有另一个元素(如果是这种情况则抛出异常),而First()在获取后停止.如果序列为空,则两者都抛出异常.

个人而言,我总是使用First().

  • 在他们生成的SQL中,如果我没有弄错的话,First()会做TOP 1而Single()会做TOP 2. (2认同)

小智 8

关于性能:一位同事和我正在讨论Single vs First(或SingleOrDefault vs FirstOrDefault)的性能,我正在争论First(或FirstOrDefault)会更快并提高性能(我只是为了制作我们的应用程序)跑得更快).

我已经阅读了有关Stack Overflow的几篇文章.有人说使用First而不是Single会有很小的性能提升.这是因为First只返回第一项,而Single必须扫描所有结果以确保没有重复(即:如果它在表的第一行中找到该项,它仍然会扫描每隔一行确保没有第二个值匹配条件然后会抛出错误).我觉得自己处于坚实的基础上,"第一"比"单身"更快,所以我开始证明这一点并让辩论得以休息.

我在我的数据库中设置了一个测试并添加了1,000,000行ID UniqueIdentifier外部UniqueIdentifier信息nvarchar(50)(填充了数字"0"到"999,9999"的字符串

我加载了数据并将ID设置为主键字段.

使用LinqPad,我的目标是表明如果你使用Single搜索'Foreign'或'Info'的值,那将比使用First更糟糕.

我无法解释我得到的结果.几乎在所有情况下,使用Single或SingleOrDefault稍微快一些.这对我来说没有任何合理意义,但我想分享一下.

例如:我使用了以下查询:

var q = TestTables.First(x=>x.Info == "314638") ;
//Vs.
Var q = TestTables.Single(x=>x.Info =="314638") ; //(this was slightly faster to my surprise)
Run Code Online (Sandbox Code Playgroud)

我在'外部'关键字段上尝试了类似的查询,这个字段没有被编入索引,认为First会更快,但Single在我的测试中总是稍微快一些.

  • 如果位于索引字段上,则数据库无需进行扫描以确保其唯一性。它已经知道了。因此,那里没有开销,服务器端的唯一开销是确保仅返回一条记录。自己进行性能测试不是一种决定性的方法 (2认同)

小智 5

它们是不同的.它们都断言结果集不为空,但是单个也断言结果不超过1.我个人使用Single,我只希望得到1个结果,因为得到多于1个结果是一个错误,可能应该这样对待.


Cha*_*ion 5

您可以尝试简单的示例以获取差异。第三行将引发异常;

        List<int> records = new List<int>{1,1,3,4,5,6};
        var record = records.First(x => x == 1);
        record = records.Single(x => x == 1);
Run Code Online (Sandbox Code Playgroud)