简体   繁体   中英

Why is IList not deferred execution?

As I understand it IEnumerable and IQueryable are deferred execution. Why wouldn't it be of benefit for IList to also support deferred execution?

The longer I think about it, the more I question whether the whole idea of "deferred execution" is actually of pedagogic value at all.

I'll answer your question by denying it. IEnumerable<T> , IQueryable<T> and IList<T> do not in any way represent "deferred" or "eager" calculations.

Rather, interfaces represent an ability to provide a service . IEnumerable<T> represents the service "I can provide a sequence, possibly infinite, of items of type T, one at a time". IQueryable<T> represents the service "I can represent a query against a data source, and provide the results of that query on demand". IList<T> represents the service "I can provide random access to a possibly mutable, finite-sized list of items of type T".

None of those services say anything about the implementation details of the service providers. The provider of an IList<T> service could be entirely lazy; the provider of an IQueryable<T> service could be entirely eager. If you want to make a deferred-execution IList<T> , you go right ahead. No one is stopping you!

IList<T> supports random access via the indexer - as well as the Count property. Both of these go against the spirit of deferred execution with streaming data, unless you're suggesting that you really just want something which loads the entire list as soon as you access anything . If that's what you're after, Lazy<T> might be the ticket...

As @Joe pointed out, IList<T> abstracts a noun . IEnumerable<T> and IQueryable<T> are abstractions of verbs .

IList<T> is an abstraction of a collection that can be treated as a list. IEnumerable<T> and 'IQueryable abstract actions: the enumeration over, or querying of the items contained in the underlying collection.

Think through the consequences of what you're saying.

What would be deferred, and until when?

In the case of IEnumerable and IQueryable what's deferred is the enumeration. And the interfaces don't expose anything else that depends on the enumeration having been done.

There are a multitude of reasons, just some:

  • an IList should be independent from the underlying data source that was used to create the IList
  • accessing an IList member by index is expected to be O(1) - with deferred execution this cannot be guaranteed - access might be very slow, at least the first time.
  • accessing an IList member should not produce an exception because of how the IList being constructed when you access (there are all sorts of problems that can arise with deferred execution, think ie not being able to access the original data source) - this is going back to the first point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM