LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria

前端 未结 15 1003
我在风中等你
我在风中等你 2020-11-22 12:48

Consider the IEnumerable extension methods SingleOrDefault() and FirstOrDefault()

MSDN documents that SingleOrDefault:

相关标签:
15条回答
  • 2020-11-22 13:03

    In my opinion FirstOrDefault is being overused a lot. In the majority of the cases when you’re filtering data you would either expect to get back a collection of elements matching the logical condition or a single unique element by its unique identifier – such as a user, book, post etc... That’s why we can even get as far as saying that FirstOrDefault() is a code smell not because there is something wrong with it but because it’s being used way too often. This blog post explores the topic in details. IMO most of the times SingleOrDefault() is a much better alternative so watch out for this mistake and make sure you use the most appropriate method that clearly represents your contract and expectations.

    0 讨论(0)
  • 2020-11-22 13:04

    I use SingleOrDefault in situations where my logic dictates that the will be either zero or one results. If there are more, it's an error situation, which is helpful.

    0 讨论(0)
  • 2020-11-22 13:09

    In your cases, I would use the following:

    select by ID==5: it's OK to use SingleOrDefault here, because you expect one [or none] entity, if you got more than one entity with ID 5, there's something wrong and definitely exception worthy.

    when searching for people whose first name equals "Bobby", there can be more than one (quite possibly I would think), so you should neither use Single nor First, just select with the Where-operation (if "Bobby" returns too many entities, the user has to refine his search or pick one of the returned results)

    the order by creation date should also be performed with a Where-operation (unlikely to have only one entity, sorting wouldn't be of much use ;) this however implies you want ALL entities sorted - if you want just ONE, use FirstOrDefault, Single would throw every time if you got more than one entity.

    0 讨论(0)
  • 2020-11-22 13:10

    There is

    • a semantical difference
    • a performance difference

    between the two.

    Semantical Difference:

    • FirstOrDefault returns a first item of potentially multiple (or default if none exists).
    • SingleOrDefault assumes that there is a single item and returns it (or default if none exists). Multiple items are a violation of contract, an exception is thrown.

    Performance Difference

    • FirstOrDefault is usually faster, it iterates until it finds the element and only has to iterate the whole enumerable when it doesn't find it. In many cases, there is a high probability to find an item.

    • SingleOrDefault needs to check if there is only one element and therefore always iterates the whole enumerable. To be precise, it iterates until it finds a second element and throws an exception. But in most cases, there is no second element.

    Conclusion

    • Use FirstOrDefault if you don't care how many items there are or when you can't afford checking uniqueness (e.g. in a very large collection). When you check uniqueness on adding the items to the collection, it might be too expensive to check it again when searching for those items.

    • Use SingleOrDefault if you don't have to care about performance too much and want to make sure that the assumption of a single item is clear to the reader and checked at runtime.

    In practice, you use First / FirstOrDefault often even in cases when you assume a single item, to improve performance. You should still remember that Single / SingleOrDefault can improve readability (because it states the assumption of a single item) and stability (because it checks it) and use it appropriately.

    0 讨论(0)
  • 2020-11-22 13:12

    Whenever you use SingleOrDefault, you clearly state that the query should result in at most a single result. On the other hand, when FirstOrDefault is used, the query can return any amount of results but you state that you only want the first one.

    I personally find the semantics very different and using the appropriate one, depending on the expected results, improves readability.

    0 讨论(0)
  • 2020-11-22 13:14

    So as I understand now, SingleOrDefault will be good if you are querying for data that is guaranteed to be unique i.e. enforced by DB constraints like primary key.

    Or is there a better way of querying for the primary key.

    Assuming my TableAcc has

    AccountNumber - Primary Key, integer
    AccountName
    AccountOpenedDate
    AccountIsActive
    etc.
    

    and I want to query for an AccountNumber 987654, I use

    var data = datacontext.TableAcc.FirstOrDefault(obj => obj.AccountNumber == 987654);
    
    0 讨论(0)
提交回复
热议问题