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);
}
Related
I'm trying to implement a custom LinQ Count() method. Basically what I'm trying to achieve here is before calling the Count method, I want to filter out all elements that have the property IsDeleted set to true. So, I created an extension class and I added these methods:
public static int Count2<T>(this IEnumerable<T> source, Func<T, bool> selector)
where T : Model
{
return source.Where(x => !x.IsDeleted).Count(selector);
}
public static int Count2<T>(this IQueryable<T> source, Expression<Func<T, bool>> selector)
where T : Model
{
return source.Where(x => !x.IsDeleted).Count(selector);
}
public static int Count2<T>(this IEnumerable<T> source)
where T : Model
{
return source.Count(x => !x.IsDeleted);
}
public static int Count2<T>(this IQueryable<T> source)
where T : Model
{
return source.Count(x => !x.IsDeleted);
}
This works just find for local collections, but when executing this command for instance:
ListOfModels.Sum(x => x.PropertyThatIsAList.Count2())
and ListOfModels is an instance of IQueryable, i.e. it has to be executed in the database, it gives me this error:
The LINQ expression 'Sum()' could not be translated and will be evaluated locally.
I looked around on the web and I saw some answers saying I have to implement the IQueryableProvider but I think there is no need to go into such complicated path since the Sum() and Count() are translatable, I only need to count conditionally. Is it possible, and if it is, can anyone give me a clue on how to do it?
I suggest you instead of customizing all LinQ methods use an extended method like Validate():
public static IEnumerable<T> Validate<T>(this IEnumerable<T> list) where T: IDeleteable
{
return list.Where(w => !w.IsDeleted);
}
That IDeleteable interface is like this:
public interface IDeleteable
{
bool IsDeleted { get; set; }
}
Then use it before other methods.
I am trying to create an extension method that "extends" on an IEnumerable of a type, accepts an expression as a parameter and returns an IEnumerable of the same type.
public static IEnumerable<T> CustomExtension<T>(this IEnumerable<T> cities, Expression<Func<T, bool>> predicate)
{
return Enumerable.Where(cities, predicate);
//the line above is wrong, doesn't compile, but it explains my intentions...
}
Then call it like so:
var bigCities = cities.CustomExtension(c => c.occupants >= 1000000);
OR
var coldCities = cities.CustomExtension(c => c.avgTemp <= 20);
NOTE: It isn't just for "city" objects, the plan is to keep it generic so I can use the same method on similar types
Thanks in advance...
public static IEnumerable<T> CustomExtension<T>(this IEnumerable<T> cities, Func<T, bool> predicate)
{
return cities.Where(x => predicate(x));
}
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 have the following linq extension method, which returns an IEnumerable. This means, that this piece of code ends up hitting the DB, before the rest of the linq statement has been finished.
Is it possible to refactor this so it returns an IQueryable instead?
public static IEnumerable<TSource> WhereIf<TSource>
(this IEnumerable<TSource> source, bool condition,
Func<TSource, bool> predicate)
{
return condition ? source.Where(predicate) : source;
}
How about?
var queryable = source.AsQueryable();
return condition ? queryable.Where(predicate) : queryable;
Link
How about the following:
public static IQueryable<TSource> WhereIf<TSource>
(this IQueryable<TSource> source, bool condition,
Func<TSource, bool> predicate)
{
return condition ? source.Where(predicate) : source;
}
If you change IEnumerable to IQueryable, then source.Where would also return an IQueryable when called, and seeing as source itself would be an IQueryable, the whole return statement would succeed in either case.
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;
}