1

Can someone explain if these two Linq statements are same or do they differ in terms of execution. I am guessing the result of their execution is the same but please correct me if I am wrong.

var k = db.MySet.Where(a => a.Id == id).SingleOrDefault().Username;
var mo = db.MySet.SingleOrDefault(a => a.Id == id).Username;
Philip Kendall
  • 4,304
  • 1
  • 23
  • 42
Flood Gravemind
  • 3,773
  • 12
  • 47
  • 79
  • You should check the `SQL` queries that are being generated. – MarcinJuraszek Sep 02 '13 at 12:45
  • Regarding performance: http://stackoverflow.com/questions/10110013/order-of-linq-extension-methods-does-not-affect-performance – Tim Schmelter Sep 02 '13 at 12:46
  • @MarcinJuraszek: nobody has said that SQL was in use here. – Philip Kendall Sep 02 '13 at 12:48
  • 1
    @PhilipKendall Both queries starts with `db.MySet` so I assumed it's a DB query. – MarcinJuraszek Sep 02 '13 at 12:48
  • FYI: `SingleOrDefault()` will throw if two elements fullfill the requirement instead of returning `null` (as the name maybe suggests). By directly accessing an element property you don't support the default state (`null`) anymore. So it would be cleaner to say `Single().Username`. – Oliver Sep 02 '13 at 13:42

6 Answers6

10

Yes, both instructions are functionally equivalent and return the same result. The second is just a shortcut.

However, I wouldn't recommend writing it like this, because SingleOrDefault will return null if there is no item with the specified Id. This will result in a NullReferenceException when you access Username. If you don't expect it to return null, use Single, not SingleOrDefault, because it will give you a more useful error message if your expectation is not met. If you're not sure that a user with that Id exists, use SingleOrDefault, but check the result before accessing its members.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
4

yes. these two linq statements are same. but i suggest you wirte code like this:

var mo = db.MySet.SingleOrDefault(a => a.Id == id);
if(mo !=null)
{
  string username=mo.Username;
}
Tim.Tang
  • 3,158
  • 1
  • 15
  • 18
3
var k = db.MySet.Where(a => a.Id == id).SingleOrDefault().Username;
var mo = db.MySet.SingleOrDefault(a => a.Id == id).Username;

You asked if they are equivalent...

  • Yes, they will return the same result, both in LINQ-to-Objects and in LINQ-to-SQL/Entity-Framework

  • No, they aren't equal, equal in LINQ-to-Objects. Someone had benchmarked them and discovered that the first one is a little faster (because the .Where() has special optimizations based on the type of db.MySet) Reference: https://stackoverflow.com/a/8664387/613130

Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
2

They're different in the terms of actual code they will execute, but I can't see a situation in which they will give different results. In fact, if you've got Resharper installed, it will recommend you change the former into the latter.

However, I'd in general question why you ever want to do SingleOrDefault() without immediately following it with a null check.

Philip Kendall
  • 4,304
  • 1
  • 23
  • 42
1

Instead of checking for null I always check for default(T) as the name of the LINQ function implies too. In my opinion its a bit more maintainable code in case the type is changed into a struct or class.

Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
0

They will both return the same result (or both will throw a NULL reference exception). However, the second one may be more efficient.

The first version will need to enumerate all values that meet the where condition, and then it will check to see if this returned only 1 value. Thus this version might need to enumerate over 100s of values.

The second version will check for only one value that meets the condition at the start. As soon as that version finds 2 values, it will thrown an exception, so it does not have the overhead of enumerating (possibly) 100s of values that will never be used.

user2735420
  • 106
  • 5
  • Both will enumerate over whole source collection. `Single`/`SingleOrDefault` does not end work after it find second matching item. – MarcinJuraszek Sep 02 '13 at 13:54