.net LINQ Single vs First
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2724096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
LINQ Single vs First
提问by Ian Vink
LINQ:
林克:
Is it more efficient to use the Single()operator over First()when ever I know for certain that the query will return a single record?
当我确定查询将返回单个记录时,使用Single()运算符是否更有效?First()
Is there a difference?
有区别吗?
回答by Armstrongest
If you're expecting a Single record, it's always good to be explicit in your code.
如果您期待单条记录,那么在您的代码中明确表示总是好的。
I know others have written why you use one or the other, but I thought I'd illustrate why you should NOT use one, when you meanthe other.
我知道其他人已经写过你为什么使用一个或另一个,但我想我会说明为什么你不应该使用一个,而你的意思是另一个。
Note: In my code, I will typically use FirstOrDefault()and SingleOrDefault()but that's a different question.
注意:在我的代码中,我通常会使用FirstOrDefault()andSingleOrDefault()但这是一个不同的问题。
Take, for example, a table that stores Customersin different languages using a Composite Key ( ID, Lang):
以Customers使用复合键 ( ID, Lang)以不同语言存储的表为例:
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();
This code above introduces a possible logic error ( difficult to trace ). It will return more than one record ( assuming you have the customer record in multiple languages ) but it will always return only the first one... which may work sometimes... but not others. It's unpredictable.
上面的这段代码引入了一个可能的逻辑错误(难以追踪)。它将返回多个记录(假设您有多种语言的客户记录)但它总是只返回第一个......有时可能有效......但其他人则无效。这是不可预测的。
Since your intent is to return a Single Customeruse Single();
由于您的意图是返回 Single Customeruse Single();
The following would throw an exception ( which is what you want in this case ):
以下将引发异常(这是您在这种情况下想要的):
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();
Then, you simply hit yourself on the forehead and say to yourself... OOPS! I forgot the language field! Following is the correct version:
然后,您只需敲击自己的额头,然后对自己说……哎呀!我忘了语言领域!以下是正确的版本:
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();
First()is useful in the following scenario:
First()在以下场景中很有用:
DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();
It will return ONE object, and since you're using sorting, it will be the most recent record that is returned.
它将返回一个对象,并且由于您正在使用排序,它将是返回的最新记录。
Using Single()when you feel it should explicitly always return 1 record will help you avoid logic errors.
使用Single()时感觉它应该明确,始终返回1条记录将有助于你避免逻辑错误。
回答by AlwaysAProgrammer
Single will throw an exception if it finds more than one record matching the criteria.
First will always select the first record from the list. If the query returns just 1 record, you can go with First().
如果找到多个符合条件的记录,Single 将抛出异常。First 将始终从列表中选择第一条记录。如果查询仅返回 1 条记录,则可以使用First().
Both will throw an InvalidOperationExceptionexception if the collection is empty.
Alternatively you can use SingleOrDefault(). This won't throw an exception if the list is empty
InvalidOperationException如果集合为空,两者都会抛出异常。或者,您可以使用SingleOrDefault(). 如果列表为空,这不会引发异常
回答by Diego Mendes
Single()
单身的()
Returns a single specific element of a query
When Use: If exactly 1 element is expected; not 0 or more than 1. If the list is empty or has more than one element, it will throw an Exception "Sequence contains more than one element"
返回查询的单个特定元素
何时使用:如果预期正好有 1 个元素;不为 0 或大于 1。如果列表为空或有多个元素,则会抛出异常“序列包含多个元素”
SingleOrDefault()
单或默认()
Returns a single specific element of a query, or a default value if no result found
When Use: When 0 or 1 elements are expected. It will throw an exception if the list has 2 or more items.
返回查询的单个特定元素,如果未找到结果则返回默认值
何时使用:当需要 0 或 1 个元素时。如果列表有 2 个或更多项目,它将抛出异常。
First()
第一的()
Returns the first element of a query with multiple results.
When Use: When 1 or more elements are expected and you want only the first. It will throw an exception if the list contains no elements.
返回具有多个结果的查询的第一个元素。
何时使用:当需要 1 个或多个元素并且您只想要第一个元素时。如果列表不包含任何元素,它将抛出异常。
FirstOrDefault()
首先或默认()
Returns the first element of a list with any amount of elements, or a default value if the list is empty.
When Use: When multiple elements are expected and you want only the first. Or the list is empty and you want a default value for the specified type, the same as
default(MyObjectType). For example: if the list type islist<int>it will return the first number from the list or 0 if the list is empty. If it islist<string>, it will return the first string from the list or null if the list is empty.
返回具有任意数量元素的列表的第一个元素,如果列表为空,则返回默认值。
何时使用:当需要多个元素而您只想要第一个时。或者列表为空并且您想要指定类型的默认值,与
default(MyObjectType). 例如:如果列表类型是list<int>,它将返回列表中的第一个数字,如果列表为空,则返回 0。如果是list<string>,它将返回列表中的第一个字符串,如果列表为空,则返回 null。
回答by Andrew Hare
There is a subtle, semantic difference between these two methods.
这两种方法之间存在细微的语义差异。
Use Singleto retrieve the first (and only) element from a sequence that should contain one element and no more. If the sequence has more than on element your invocation of Singlewill cause an exception to be thrown since you indicated that there should only be one element.
用于Single从一个序列中检索第一个(也是唯一一个)元素,该元素应该包含一个元素而不能包含更多元素。如果序列有多个元素,您的调用Single将导致抛出异常,因为您指示应该只有一个元素。
Use Firstto retrieve the first element from a sequence that can contain any number of elements. If the sequence has more than on element your invocation of Firstwill not cause an exception to be thrown since you indicated that you only need the first element in the sequence and do not care if more exist.
用于First从可以包含任意数量元素的序列中检索第一个元素。如果序列有多个元素,您的调用First将不会导致抛出异常,因为您指出您只需要序列中的第一个元素并且不关心是否存在更多元素。
If the sequence contains no elements both method calls will cause exceptions to be thrown since both methods expect at least one element to be present.
如果序列不包含任何元素,则两个方法调用都将导致抛出异常,因为这两个方法都期望至少存在一个元素。
回答by Patrick Karcher
If you don't specifically want an exception thrown in the event that there is more than one item, use First().
如果您不希望在有多个项目的情况下引发异常,请使用First().
Both are efficient, take the first item. First()is slightly more efficient because it doesn't bother checking to see if there is a second item.
两者都有效,取第一项。 First()稍微更有效,因为它不会费心检查是否有第二个项目。
The only difference is that Single()expects there to be only one item in the enumeration to begin with, and will throw an exception if there are more than one. You use.Single()if you specifically want an exception thrownin this case.
唯一的区别是Single()期望枚举中只有一个项目开始,如果有多个项目,将抛出异常。您使用.Single(),如果你特别想要抛出的异常在这种情况下。
回答by Etienne de Martel
If I recall, Single() checks if there is another element after the first one (and throws an exception if it's the case), while First() stops after getting it. Both throw an exception if the sequence is empty.
如果我记得,Single() 检查第一个元素之后是否还有另一个元素(如果是,则抛出异常),而 First() 在获取它后停止。如果序列为空,两者都会抛出异常。
Personnally, I always use First().
就我个人而言,我总是使用 First()。
回答by Marcus Talcott
Regarding peformance: A coworker and I were discussing the performance of Single vs First (or SingleOrDefault vs FirstOrDefault), and I was arguing for the point that First (or FirstOrDefault) would be faster and improve performance (I'm all about making our app run faster).
关于性能:我和一位同事正在讨论 Single vs First(或 SingleOrDefault vs FirstOrDefault)的性能,我争论的是 First(或 FirstOrDefault)会更快并提高性能(我完全是为了制作我们的应用程序跑得更快)。
I've read several posts on Stack Overflow that debate this. Some say there are small performance gains using First instead of Single. This is because First would simply return the first item while Single must scan all the results to make sure there isn't a duplicate (ie: if it found the item in the first row of the table, it still would scan every other row to make sure there isn't a second value matching the condition which would then throw an error). I felt like I was on solid ground with “First” being faster than “Single” so I set out to prove it and put the debate to rest.
我在 Stack Overflow 上读过几篇讨论这个问题的帖子。有人说使用 First 而不是 Single 有很小的性能提升。这是因为 First 将简单地返回第一项,而 Single 必须扫描所有结果以确保没有重复(即:如果它在表的第一行中找到该项目,它仍然会每隔一行扫描一次确保没有第二个值与条件匹配,然后会抛出错误)。我觉得我已经站稳脚跟,“First”比“Single”快,所以我开始证明这一点并让争论停止。
I setup a test in my database and added 1,000,000 rows of ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar(50) (filled with strings of numbers “0” to “999,9999”
我在我的数据库中设置了一个测试并添加了 1,000,000 行 ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar(50)(填充数字字符串“0”到“999,9999”
I loaded the data and set ID as a primary key field.
我加载了数据并将 ID 设置为主键字段。
Using LinqPad, my goal was to show that if you searched for a value on ‘Foreign' or ‘Info' using Single, that it would be much worse than using First.
使用 LinqPad,我的目标是表明,如果您使用 Single 搜索“Foreign”或“Info”上的值,这将比使用 First 糟糕得多。
I cannot explain the results I got. In almost every case, using Single or SingleOrDefault was slightly faster. This doesn't make any logical sense to me, but I wanted to share that.
我无法解释我得到的结果。在几乎所有情况下,使用 Single 或 SingleOrDefault 都稍微快一些。这对我来说没有任何逻辑意义,但我想分享一下。
Ex: I used the following queries:
例如:我使用了以下查询:
var q = TestTables.First(x=>x.Info == "314638") ;
//Vs.
Var q = TestTables.Single(x=>x.Info =="314638") ; //(this was slightly faster to my surprise)
I tried similar queries on the 'Foreign' key field which was not indexed thinking that would prove First is faster, but Single was always slightly faster in my tests.
我在“外来”键字段上尝试了类似的查询,这些查询没有被索引,这会证明 First 更快,但 Single 在我的测试中总是稍微快一点。
回答by jaltiere
They are different. Both of them assert that the result set is not empty, but single also asserts that there is not more than 1 result. I personally use Single in cases where I only expect there to be 1 result just because getting more than 1 result back is an error and probably should be treated as such.
它们是不同的。他们都断言结果集不为空,但是single也断言不超过1个结果。我个人使用 Single 在我只期望有 1 个结果的情况下,仅仅因为返回 1 个以上的结果是一个错误并且可能应该这样对待。
回答by Chauskin Rodion
You can try simple example to get difference. Exception will thrown on line 3;
您可以尝试简单的示例来获得差异。第 3 行会抛出异常;
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);
回答by Matt H
A lot of people I know use FirstOrDefault(), but I tend to use SingleOrDefault() more because often it would be some sort of data inconsistency if there were more than one. This is dealing with LINQ-to-Objects, though.
我认识的很多人都使用 FirstOrDefault(),但我更倾向于使用 SingleOrDefault(),因为如果有多个,通常会出现某种数据不一致。不过,这是在处理 LINQ-to-Objects。

