myList.Where(x => x.name = 'Person');
.Where(x => x.age > 18);
.ToList();
it wouldn't actually run two different array filters - it would combine them. You can imagine the performance gains to be had there. myList.Where(x => x.name = 'Person');
.Where(x => x.age > 18);
.ToList();
it wouldn't actually run two different array filters - it would combine them. You can imagine the performance gains to be had there. public static IEnumerable<T> Where<T>(IEnumerable<T> source,
Predicate<T> predicate)
{
foreach(var item in source)
{
if(predicate(item))
yield return item;
}
}
which means var results = myList
.Where(x => x.name == 'Person');
.Where(x => x.age > 18);
.ToList();
is executed just like var results = new List<Foo>();
foreach(var x in myList)
{
if(x.name == 'Person')
{
if(x.age > 18)
results.Add(x);
}
}In fact, how else could "Where" be implemented while keeping lazy semantics?
(Rust, AFAIK, can actually do this, by inlining everything including the lambdas.)
You're right it's missing the actual function calls, but that wasn't the point: the point here was that LINQ avoids building temporary enumerations and iterating over them like JS functions do.
But here's a microbenchmark[1]. It's still not close to non-LINQ code. A factor of 10, with a trivial body, just summing up some numbers. (I didn't used Sum() as it appears to use checked arithmetic.)
As far as the optimizations, the smart combining code (which still has to allocate a combined delegate + lambda object, that'll cost, what 2 objects at like 40 bytes each?)) only happens when Select is followed by Select, or Where by Where. Select after Where gets a new "WhereSelectEnumerableIterator" and so on.
So you're right that it does eliminate some overhead though depending on the order of your Wheres and Selects there may be more "foreach" loops in the comparable code. And it's still not even close to being free like it should be. (Like, say, Haskell can do sometimes.)
_(myList)
.filter(x => x.name == 'Person')
.filter(x => x.age > 18)
.value()
Used like this Lodash is lazy, so the first value of myList will run through all the filters before the next item gets processed._.where(listOfPlays, {author: "Shakespeare", year: 1611});
LINQ doesn't just combine Wheres. It tries to optimize your query as much as possible and executes lazily, so you aren't actually doing any work until you try to use the resultset (in a ToList, for example).
[0]: https://lodash.com/