LINQ Any () and Single () versus Zero Validated SingleOrDefault ()

In which cases is each solution preferable to the other?

Example 1:

if (personList.Any(x => x.Name == "Fox Mulder")) { this.Person = personList.Single(x => x.Name == "Fox Mulder"); } 

Example 2:

 var mulder = personList.SingleOrDefault(x => x.Name == "Fox Mulder"); if (mulder != null) { this.Person = mulder; } 
+6
source share
3 answers

Both Single and SingleOrDefault will enumerate the collection beyond the first matching result to ensure that there is exactly one item matching the criteria, stopping either at the next match or at the end of the collection. The first example will be a bit slower, since the Any call will enumerate enough of the collection (perhaps all of this) to determine whether any elements meet the criteria, stopping either at the first match or at the end of the collection.

There is another critical difference: the first example may throw an exception. Single will return the corresponding element if it is exactly one, and otherwise throw an exception. Validation with Any does not validate this; he only checks that there is at least one.

Based on these two reasons (primarily / especially the second reason), the SingleOrDefault approach is preferable here.


So there are three cases.

Case 1: no items match the condition

Option 1: .Any lists the entire set and returns false; .Single never executed.

Option 2: .SingleOrDefault lists the entire set and returns null.

The options are essentially equivalent.

Case 2: Exactly one element meets the condition

Option 1: Any lists enough set to search for a single match (may be the first element, may be the entire set). Single then lists the entire set to find one item and confirm that other conditions do not meet this condition.

Option 2: SingleOrDefault lists the entire set, returns a single match.

In this case, option 2 is better (exactly one iteration compared to (1, 2] iterations)

Case 3: more than one item meets the condition

Option 1: Any lists enough to find the first match. Single lists enough to find the second match, throws an exception.

Option 2: SingleOrDefault lists enough to find the second match, throws an exception.

Both throw exceptions, but option 2 gets faster.

+8
source

Extrapolation from recommendations is v. as :

See Casting vs below using the 'as' keyword in the CLR :

 // Bad code - checks type twice for no reason if (randomObject is TargetType) { TargetType foo = (TargetType) randomObject; // Do something with foo } 

Using Any and Single , you also double check the list. And the same logic is apparently applicable: Not only is this checking twice, but it may be checking different things, that is, in a multi-threaded application, the list may differ between verification and assignment. In extreme cases, an element found using Any may not exist when calling Single .

Using this logic, I would benefit by way of example two in all cases until a proof is given.

0
source

Option 3:

 this.Person = personList.FirstOrDefault(x => x.Name == "Fox Mulder"); 

if Entity Framework is used, and the name is the primary key, then:

 this.person = db.personList.Find("Fox Mulder"); 

Both of these operations, if this.Person is null, or if the person is not found, you expect this.Person be overwritten with zero. FirstOrDefault is the fastest, as it stops at the first record, which matches instead of repeating throughout the collection, but it will not throw an exception if several are found. An entity framework solution is even better in this case, because Find will use the EF cache, possibly without even getting to the data source.

0
source

All Articles