25

I have some IEnumberable collection of items. I use .Single() to find a specific object in the collection.

I choose to use Single() because there should only ever be one specific item. However, if one doesn't exist, then I need to create it and add it to the collection.

My problem is that Single() throws the same error if there is no item matching the predicate or if there are multiple items. My idea was to put the Single() call inside of a try and catch the exception, add the item, and then continue. However, since both scenarios throw the InvalidOperationException, how can I tell if its due to no items or multiple items?

I know I can use First() but that doesn't enforce the idea that there should be only one (without doing extra work).

I could also use Count() before the Single() call, but that just seems to undermine the point of Single()

Justin Self
  • 6,137
  • 3
  • 33
  • 48

3 Answers3

40

What you want is SingleOrDefault()

The "or default" actually means it returns null (for reference types) or whatever the default would be for a non-reference type. You'll need to new-up an object to take its place.

Michael Dunlap
  • 4,300
  • 25
  • 36
  • 6
    Well, it returns the default value for the element type. That's null for reference types, but obviously not for non-nullable value types... – Jon Skeet Nov 21 '12 at 17:12
  • 1
    ...and if you want to chain null check, may use something like this http://napoleonss.wordpress.com/2011/12/20/my-check-null/. Works for defaults on types – napoleonss Nov 21 '12 at 17:12
  • @JonSkeet You are correct. I assumed he was talking about a reference type though. – Michael Dunlap Nov 21 '12 at 17:17
  • 1
    @DigitalD: Yes, probably in this case. It's just that your second sentence makes it sound like you'd have named the method `SingleOrNull`, which wouldn't have been reasonable. – Jon Skeet Nov 21 '12 at 17:17
5

I wouldn't recommend using the try/catch in this scenario, because using exceptions to make logical decisions is resource expensive.

I would recommend using SingleOrDefault(), and check if the result is null. If it is. Do your creation.

Khan
  • 17,904
  • 5
  • 47
  • 59
  • 7
    "resource expensive" - is somewhat of an antiquated/incorrect view. See the Rico Mariani link provided here. http://stackoverflow.com/q/891217/16391. I do agree that using exceptions to make logical decisions is a poor design choice. – StingyJack Nov 21 '12 at 17:14
1

SingleOrDefault will throw an exception when there is more than one item in the set. You will have to check for the size beforehand manually.

var singleItem = list.Count() == 1 ? list.Single() : null;

Maybe it's best to just make your own extension function.

apoth
  • 13
  • 3