Wilsonhut

Deal with it or don't

SingleOrDefault overload with default

Ever have to write something like this?:

var theOneIWant = someListOfThings.SingleOrDefault(thing => thing.IsMostAwesome) ?? Thing.Empty;

…which is simply abhorrent. You’d rather write something like this:

var theOneIWant = someListOfThings.SingleOrDefault(thing => thing.IsMostAwesome, Thing.Empty);

…SO much better.

Well, your wait is over. Now you can.

public static T SingleOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate, T defaultValue)
{
  return source.SingleOrDefault(predicate, () => defaultValue);
}
 
public static T SingleOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> getDefaultValue)
{
	if (source == null)
		throw new ArgumentNullException("source");
	if (predicate == null)
		throw new ArgumentNullException("predicate");
	var single = default(T);
	int num = 0;
	foreach (var item in source.Where(predicate))
	{
		single = item;
		if (++num > 1)
		{
			break;
		}
	}
	switch (num)
	{
		case 0:
			return getDefaultValue();
		case 1:
			return single;
		default:
			throw new InvalidOperationException("Sequence contains more than one element");
	}
}

Also, if obtaining the default value is expensive, you can use the overload that takes a lambda, so it’s only executed if it’s needed.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: