Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEnumerable<T> as return value, deferred execution and N-tier applications

First, I do not consider this question be the dup of these SO questions:

Should I always return IEnumerable<T> instead of IList<T>? and IEnumerable<T> as return type

As we all know ont of the main purposes of introducing several tiers is to decrease coupling.
We must define some interface for data access and our BL should not care about the details of DAL implementation. If mentioned interface returnes IEnumerable<T> BL does not know whether it is just a static IEnumerable or something that has deferred execution. At the same time this particular detail can affect perfromance considerably and requires different coding depending on the implementation.
Well, it is possible to call .ToList() for each IEnumerable in situations when we are going to iterate collection several times. But this decreases perfromance for static collections because of unnecessary new list instantiation.

So I'm trying to understand which approach is better.
More universal and potentially less performant vs More coupled-more performant. I guess, there's no silver bullet but it could be other approaches I've missed.

like image 914
Pavel Voronin Avatar asked Jan 28 '13 16:01

Pavel Voronin


People also ask

How to implement deferred execution for custom extension methods for IEnumerable?

You can implement deferred execution for your custom extension methods for IEnumerable using the yield keyword of C#. For example, you can implement custom extension method GetTeenAgerStudents for IEnumerable that returns a list of all students who are teenagers.

What is deferred execution in a LINQ query?

It seems confused at first, but it’s worth to remember that deferred execution is a feature of LINQ query, no matter on which data source. LINQ queries are always executed when the query variable is iterated over, not when the query variable is created.

How do you fix IEnumerable is not working?

If the underlying type of the IEnumerable collection is an iterator-based implementation generated by LINQ methods like Select or yield in C# or yield statement in Visual Basic, you can fix the violation by converting and caching the collection to another type. However, this allocates extra memory.

What is the difference between IEnumerable and list interface?

Remember, the interface tells you what is expected to be returned. IEnumerable only means you are getting something that can be iterated over (potentially streaming results and making use of deferred execution), and List only means you're getting an in-memory collection that can be added to, removed from, accessed by index, etc.


2 Answers

So I'm trying to understand which approach is better: more universal and less performant vs more coupled and more performant.

First, though that is an interesting tradeoff, in this case I would think that the relevant tradeoff is actually correct vs incorrect, which surely trumps any question of performance. A deferred-execution query usually has the property that it gives you the most up to date results of the query, whereas calling ToList gives you a snapshot of a past version of the query results. There are surely cases where one is correct and the other is incorrect.

Second, assuming that you have dealt with the correctness issue and really do have a performance tradeoff to make, the tradeoff you actually want to make is: more universal and unacceptable performance vs more coupled and acceptable performance, at which is becomes clear that you have to choose the one with acceptable performance.

If both have acceptable performance and one is a few nanoseconds slower than the other, or consumes a few bytes more memory than the other, and both are correct, then who cares which one you choose? Spend your valuable time thinking about something else. And if neither have acceptable performance then you have a bigger problem to solve.

like image 194
Eric Lippert Avatar answered Sep 28 '22 18:09

Eric Lippert


If it's important, conceptually, for the caller to know that the return type of the method is a List and not an IEnumerable (for example, to know that there will be no negative consequences for iterating it multiple times), then you should return a List. The point of returning the interface instead is a way of saying, "It doesn't matter what the implementation is." If the implementation does matter, then don't use the interface (in that specific situation).

like image 34
Servy Avatar answered Sep 28 '22 20:09

Servy