The IEnumerable extension method FirstOrDefault didn't exactly do as I wanted so I created FirstOrValue. Is this a good way to go about this or is there a better way?
public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, T value)
{
T first = source.FirstOrDefault(predicate);
return Equals(first, default(T)) ? value : first;
}
Your code is probably incorrect; you probably haven't considered all of the cases.
Of course, we cannot know if any code is correct or incorrect until we have a spec. So start by writing a one-line spec:
"FirstOrValue<T> takes a sequence of T, a predicate, and a value of T, and returns either the first item in the sequence that matches the predicate if there is one, or, if there is not, the stated value."
Does your attempt actually implement that spec? Certainly not! Test it:
int x = FirstOrValue<int>( new[] { -2, 0, 1 }, y=>y*y==y, -1);
this returns -1. The correct answer according to the spec is 0. The first item that matches the predicate is zero, so it should be returned.
A correct implementation of the spec would look like:
public static T FirstOrValue<T>(this IEnumerable<T> sequence, Func<T, bool> predicate, T value)
{
if (sequence == null) throw new ArgumentNullException("sequence");
if (predicate == null) throw new ArgumentNullException("predicate");
foreach(T item in sequence)
if (predicate(item)) return item;
return value;
}
Always write a spec first, even if it's only a single sentence.
default(T) will return null by default for reference types.
I would do this
public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, T value)
{
T first = source.FirstOrDefault(predicate);
return first ?? value;
}
Since this is an overload, it's worth mentioning the version with no predicate.
public static T FirstOrValue<T>(this IEnumerable<T> sequence, T value)
{
if (sequence == null) throw new ArgumentNullException("sequence");
foreach(T item in sequence)
return item;
return value;
}
Seems reasonable to me if you want to tweak the readability instead of using DefaultIfEmpty.
You could also create an override that uses a lambda if the creation of the default value is expensive, creating it only if necessary.
public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> getValue)
{
T first = source.FirstOrDefault(predicate);
return Equals(first, default(T)) ? getValue() : first;
}
Related
I'm producing a list of decimal values from a LINQ expression and I want the minimum non zero value. However it's entirely possible that the LINQ expression will result in an empty list.
This will raise an exception and there is no MinOrDefault to cope with this situation.
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).Min();
How can I set the result to 0 if the list is empty?
What you want is this:
IEnumerable<double> results = ... your query ...
double result = results.MinOrDefault();
Well, MinOrDefault() does not exist. But if we were to implement it ourselves it would look something like this:
public static class EnumerableExtensions
{
public static T MinOrDefault<T>(this IEnumerable<T> sequence)
{
if (sequence.Any())
{
return sequence.Min();
}
else
{
return default(T);
}
}
}
However, there is functionality in System.Linq that will produce the same result (in a slightly different way):
double result = results.DefaultIfEmpty().Min();
If the results sequence contains no elements, DefaultIfEmpty() will produce a sequence containing one element - the default(T) - which you subsequently can call Min() on.
If the default(T) is not what you want, then you could specify your own default with:
double myDefault = ...
double result = results.DefaultIfEmpty(myDefault).Min();
Now, that's neat!
decimal? result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
Note the conversion to decimal?. You'll get an empty result if there are none (just handle that after the fact - I'm mainly illustrating how to stop the exception). I also made "non-zero" use != rather than >.
The neatest in terms of just doing it once in a small amount code is, as already mentioned:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).DefaultIfEmpty().Min();
With casting itm.Amount to decimal? and obtaining the Min of that being the neatest if we want to be able to detect this empty condition.
If however you want to actually provide a MinOrDefault() then we can of course start with:
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min(selector);
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().Min(selector);
}
You now have a full set of MinOrDefault whether or not you include a selector, and whether or not you specify the default.
From this point on your code is simply:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).MinOrDefault();
So, while it's not as neat to begin with, it's neater from then on.
But wait! There's more!
Let's say you use EF and want to make use of the async support. Easily done:
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync(selector);
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().MinAsync(selector);
}
(Note that I don't use await here; we can directly create a Task<TSource> that does what we need without it, and hence avoid the hidden complications await brings).
But wait, there's more! Let's say we're using this with IEnumerable<T> some times. Our approach is sub-optimal. Surely we can do better!
First, the Min defined on int?, long?, float? double? and decimal? already do what we want anyway (as Marc Gravell's answer makes use of). Similarly, we also get the behaviour we want from the Min already defined if called for any other T?. So let's do some small, and hence easily inlined, methods to take advantage of this fact:
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source, TSource? defaultValue) where TSource : struct
{
return source.Min() ?? defaultValue;
}
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source) where TSource : struct
{
return source.Min();
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector, TResult? defaultValue) where TResult : struct
{
return source.Min(selector) ?? defaultValue;
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector) where TResult : struct
{
return source.Min(selector);
}
Now let's start with the more general case first:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
{
if(default(TSource) == null) //Nullable type. Min already copes with empty sequences
{
//Note that the jitter generally removes this code completely when `TSource` is not nullable.
var result = source.Min();
return result == null ? defaultValue : result;
}
else
{
//Note that the jitter generally removes this code completely when `TSource` is nullable.
var comparer = Comparer<TSource>.Default;
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(comparer.Compare(current, currentMin) < 0)
currentMin = current;
}
return currentMin;
}
}
return defaultValue;
}
Now the obvious overrides that make use of this:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source)
{
var defaultValue = default(TSource);
return defaultValue == null ? source.Min() : source.MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
return source.Select(selector).MinOrDefault();
}
If we're really bullish about performance, we can optimise for certain cases, just like Enumerable.Min() does:
public static int MinOrDefault(this IEnumerable<int> source, int defaultValue)
{
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(current < currentMin)
currentMin = current;
}
return currentMin;
}
return defaultValue;
}
public static int MinOrDefault(this IEnumerable<int> source)
{
return source.MinOrDefault(0);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector, int defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
{
return source.Select(selector).MinOrDefault();
}
And so on for long, float, double and decimal to match the set of Min() provided by Enumerable. This is the sort of thing where T4 templates are useful.
At the end of all that, we have just about as performant an implementation of MinOrDefault() as we could hope for, for a wide range of types. Certainly not "neat" in the face of one use for it (again, just use DefaultIfEmpty().Min()), but very much "neat" if we find ourselves using it a lot, so we have a nice library we can reuse (or indeed, paste into answers on StackOverflow…).
This approach will return the single smallest Amount value from itemList. In theory this should avoid multiple round trips to the database.
decimal? result = (from Item itm in itemList
where itm.Amount > 0)
.Min(itm => (decimal?)itm.Amount);
The null reference exception is no longer caused because we are using a nullable type.
By avoiding the use of executing methods such as Any before calling Min, we should only be making one trip to the database
If itemList is non-nullable (where DefaultIfEmpty gives 0) and you want null as a potential output value, you can use the lambda syntax as well:
decimal? result = itemList.Where(x => x.Amount != 0).Min(x => (decimal?)x);
decimal result;
try{
result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
}catch(Exception e){
result = 0;
}
What difference between
FirstOrDefault(someField => someField.Name.Equals(settings.Text))
and
Where(someField => someField.Name.Equals(settings.Text)).FirstOrDefault()
?
As far as I understand in both cases Linq will run till the first occurence that suits the condition.
They result of both statements is the same. You can think of the first one as a shorter version of the second one.
The FirstOrDefault method has an overload taking in a second parameter, a Func<TSource, bool> which is the same predicate you are defining in your Where statement.
If we are talking about Linq to Objects, then there is one notable difference. Second statement
Where(someField => someField.Name.Equals(settings.Text)).FirstOrDefault()
Will create WhereEnumerableIterator internally, and then it will start enumeration and take first item:
// argument checks and collection optimizations removed
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
// it enumerates source and returns items which match predicate
return new WhereEnumerableIterator<TSource>(source, predicate);
}
public static TSource First<TSource>(this IEnumerable<TSource> source)
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
return enumerator.Current;
}
throw Error.NoElements();
}
But first statement will just take first item from source which matches predicate without creating additional enumerator:
// argument checks removed
public static TSource First<TSource>(
this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (TSource local in source)
{
if (predicate(local))
return local;
}
throw Error.NoMatch();
}
So, first one is better in terms of performance:
FirstOrDefault(someField => someField.Name.Equals(settings.Text))
I've been running into situations where I feel I'm lacking a LINQ extension method which effectivelly checks if there is no match of the specified predicate in a collection. There is Any and All, but if I for instance use the following code:
if (Objects.All(u => u.Distance <= 0))
This returns true if all the objects in the collection are 0 or less yards away.
if (Objects.Any(u => u.Distance <= 0))
This returns true if there is at least one object in the collection which is 0 or less yards away from me.
So far so good, both those methods make sense and the syntax for them makes sense too. Now, if I want to check if there is no object with 0 or less distance, I'd have to invert the predicate inside the All method to >= 0 instead of <= 0 or call !All(), which in some cases results in very poorly readable code.
Is there no method which effectively does Collection.None(u => u.Distance <= 0) to check if there is no object in the collection which is 0 or less yards away? It's syntactic sugar more than an actual problem, but I just have the feeling it's missing.
None is the same as !Any, so you could define your own extension method as follows:
public static class EnumerableExtensions
{
public static bool None<TSource>(this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
return !source.Any(predicate);
}
}
You can write your own Extension Method:
public static bool None(this IEnumerable<T> collection, Func<T, bool> predicate)
{
return collection.All(p=>predicate(p)==false);
}
Or on IQueryable<T> as well
public static bool None(this IQueryable<T> collection, Expression<Func<TSource, bool>> predicate)
{
return collection.All(p=> predicate(p)==false);
}
Even shorter version
static class LinqExtensions
{
public static bool None<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) => !source.Any(predicate);
}
I know when Linq's Any() extension is used to determine if an enumerable has at least one element it will only consume a single element. But how does that work actually? Does it have to cast all items in the enumerable first, or does it just cast them one at a time, starting with the first and stopping there?
Any() works on an IEnumerable<T> so no cast is required. It's implementation is very simple, it simply iterates through the enumerable and sees if it can find any elements matching the specified criteria.
Simple implementation looks like:
public bool Any<T>(IEnumerable<T> list)
{
using (var enumerator = list.GetEnumerator())
{
return enumerator.MoveNext();
}
}
So, no any casting required
Code in the public static class Enumerable:
public static bool Any<TSource>(this IEnumerable<TSource> source) {
if(source==null) {
throw Error.ArgumentNull("source");
}
using(IEnumerator<TSource> enumerator=source.GetEnumerator()) {
if(enumerator.MoveNext()) {
return true;
}
}
return false;
}
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if(source==null) {
throw Error.ArgumentNull("source");
}
if(predicate==null) {
throw Error.ArgumentNull("predicate");
}
foreach(TSource local in source) {
if(predicate(local)) {
return true;
}
}
return false;
}
Not seen the casting, but generic.
I'm producing a list of decimal values from a LINQ expression and I want the minimum non zero value. However it's entirely possible that the LINQ expression will result in an empty list.
This will raise an exception and there is no MinOrDefault to cope with this situation.
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).Min();
How can I set the result to 0 if the list is empty?
What you want is this:
IEnumerable<double> results = ... your query ...
double result = results.MinOrDefault();
Well, MinOrDefault() does not exist. But if we were to implement it ourselves it would look something like this:
public static class EnumerableExtensions
{
public static T MinOrDefault<T>(this IEnumerable<T> sequence)
{
if (sequence.Any())
{
return sequence.Min();
}
else
{
return default(T);
}
}
}
However, there is functionality in System.Linq that will produce the same result (in a slightly different way):
double result = results.DefaultIfEmpty().Min();
If the results sequence contains no elements, DefaultIfEmpty() will produce a sequence containing one element - the default(T) - which you subsequently can call Min() on.
If the default(T) is not what you want, then you could specify your own default with:
double myDefault = ...
double result = results.DefaultIfEmpty(myDefault).Min();
Now, that's neat!
decimal? result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
Note the conversion to decimal?. You'll get an empty result if there are none (just handle that after the fact - I'm mainly illustrating how to stop the exception). I also made "non-zero" use != rather than >.
The neatest in terms of just doing it once in a small amount code is, as already mentioned:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).DefaultIfEmpty().Min();
With casting itm.Amount to decimal? and obtaining the Min of that being the neatest if we want to be able to detect this empty condition.
If however you want to actually provide a MinOrDefault() then we can of course start with:
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min(selector);
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().Min(selector);
}
You now have a full set of MinOrDefault whether or not you include a selector, and whether or not you specify the default.
From this point on your code is simply:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).MinOrDefault();
So, while it's not as neat to begin with, it's neater from then on.
But wait! There's more!
Let's say you use EF and want to make use of the async support. Easily done:
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync(selector);
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().MinAsync(selector);
}
(Note that I don't use await here; we can directly create a Task<TSource> that does what we need without it, and hence avoid the hidden complications await brings).
But wait, there's more! Let's say we're using this with IEnumerable<T> some times. Our approach is sub-optimal. Surely we can do better!
First, the Min defined on int?, long?, float? double? and decimal? already do what we want anyway (as Marc Gravell's answer makes use of). Similarly, we also get the behaviour we want from the Min already defined if called for any other T?. So let's do some small, and hence easily inlined, methods to take advantage of this fact:
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source, TSource? defaultValue) where TSource : struct
{
return source.Min() ?? defaultValue;
}
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source) where TSource : struct
{
return source.Min();
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector, TResult? defaultValue) where TResult : struct
{
return source.Min(selector) ?? defaultValue;
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector) where TResult : struct
{
return source.Min(selector);
}
Now let's start with the more general case first:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
{
if(default(TSource) == null) //Nullable type. Min already copes with empty sequences
{
//Note that the jitter generally removes this code completely when `TSource` is not nullable.
var result = source.Min();
return result == null ? defaultValue : result;
}
else
{
//Note that the jitter generally removes this code completely when `TSource` is nullable.
var comparer = Comparer<TSource>.Default;
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(comparer.Compare(current, currentMin) < 0)
currentMin = current;
}
return currentMin;
}
}
return defaultValue;
}
Now the obvious overrides that make use of this:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source)
{
var defaultValue = default(TSource);
return defaultValue == null ? source.Min() : source.MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
return source.Select(selector).MinOrDefault();
}
If we're really bullish about performance, we can optimise for certain cases, just like Enumerable.Min() does:
public static int MinOrDefault(this IEnumerable<int> source, int defaultValue)
{
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(current < currentMin)
currentMin = current;
}
return currentMin;
}
return defaultValue;
}
public static int MinOrDefault(this IEnumerable<int> source)
{
return source.MinOrDefault(0);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector, int defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
{
return source.Select(selector).MinOrDefault();
}
And so on for long, float, double and decimal to match the set of Min() provided by Enumerable. This is the sort of thing where T4 templates are useful.
At the end of all that, we have just about as performant an implementation of MinOrDefault() as we could hope for, for a wide range of types. Certainly not "neat" in the face of one use for it (again, just use DefaultIfEmpty().Min()), but very much "neat" if we find ourselves using it a lot, so we have a nice library we can reuse (or indeed, paste into answers on StackOverflow…).
This approach will return the single smallest Amount value from itemList. In theory this should avoid multiple round trips to the database.
decimal? result = (from Item itm in itemList
where itm.Amount > 0)
.Min(itm => (decimal?)itm.Amount);
The null reference exception is no longer caused because we are using a nullable type.
By avoiding the use of executing methods such as Any before calling Min, we should only be making one trip to the database
If itemList is non-nullable (where DefaultIfEmpty gives 0) and you want null as a potential output value, you can use the lambda syntax as well:
decimal? result = itemList.Where(x => x.Amount != 0).Min(x => (decimal?)x);
decimal result;
try{
result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
}catch(Exception e){
result = 0;
}