Cheng Chen
Cheng Chen

Reputation: 43513

Which LINQ query is more effective?

I have a huge IEnumerable(suppose the name is myItems), which way is more effective?

Solution 1: Filter it first then ForEach.

Array.ForEach(myItems.Where(FILTER-IT-HERE).ToArray(),MY-ACTION);

Solution 2: Do RETURN in MY-ACTION if the item is not up to the mustard.

Array.ForEach(myItems.ToArray(),MY-ACTION-WITH-FILTER);

Is one of them always better than another? Or any other good suggestions? Thanks in advance.

Upvotes: 3

Views: 445

Answers (7)

user370770
user370770

Reputation:

The idea of LINQ is to work on enumerable collections, so the best LINQ query is the one where you don't use Array.ForEach() and .ToArray() at all.

Upvotes: 0

gerryLowry
gerryLowry

Reputation: 2646

Sometimes one has to create benchmark's because similar looking activities could produce radically different and unexpected results.

You do not say what your data source is so I'm going to assume it may be data on an SQL server in which case filtering at the server side will likely always be the best approach because you have minimized the amount of data transfer. Memory access is always faster than data transfer from disk to memory so whenever you can transfer fewer records, you are likely to have better performance.

Upvotes: 1

user315772
user315772

Reputation:

Everything else being equal, calling ToArray() first will impart a greater performance hit than when calling it last. Although, as has been stated by others before me,

  1. Why use ToArray() and Array.ForEach() at all?
  2. We don't know that everything else actually is equal since you do not reveal the implementation details of your filter and action.

Upvotes: 0

Dan Tao
Dan Tao

Reputation: 128317

If performance is a concern, it's unclear to me why you'd be bothering to construct an entire array in the first place. Why not just this?

foreach (var item in myItems.Where(FILTER-IT-HERE))
    MY-ACTION;

Or:

foreach (var item in myItems)
    MY-ACTION-WITH-FILTER;

I ask because, while the others are right that you can't really know without testing, I wouldn't expect there to be much difference between the above two options. I would expect there to be a difference, on the other hand, between creating/populating an array (seemingly for no reason) and not creating an array.

Upvotes: 0

Mark Carpenter
Mark Carpenter

Reputation: 17775

Well, both times, you're converting to an array, which might not be so efficient if the IEnumerable is very large (like you said). You could create a generic extension method for IEnumerable, like:

public static void ForEach<T>(this IEnumerable<T> current, Action<T> action) {
    foreach (var i in current) {
        action(i);
    }
}

and then you could do this:

IEnumerable<int> ints = new List<int>();
ints.Where(i => i == 5).ForEach(i => Console.WriteLine(i));

Upvotes: 0

LBushkin
LBushkin

Reputation: 131656

I would say that this falls into the category of premature optimization. If, after establishing benchmarks, you find that the code is too slow, you can always try each approach and pick the result that works better for you.

Since we don't know how the IEnumerable<> is produced it's hard to say which approach will perform better. We also don't know how many items will remain after you apply your predicate - nor do we know whether the action or iteration steps are going to be the dominant factor in the execution of your code. The only way to know for sure is to try it both ways, profile the results, and pick the best.

Performance aside, I would choose the version that is most clear - which (for me) is to first filter and then apply the projection to the result.

Upvotes: -1

Jared Peless
Jared Peless

Reputation: 1120

Did you do any measurements? Since WE can't measure the run time of My-Action then only you can. Measure and decide.

Upvotes: 1

Related Questions