What is a good way to to indicate an IEnumerable is “slow” or “fast”?

梦想与她 提交于 2019-12-07 01:10:26

问题


The answer to What is the expected performance of IEnumerable? says there's no way to know anyting about the performance of iterating an arbitrary IEnumerable. Each iteration could hit a database or make a web serivce call; or it might just return the next item in an array/list.

Given that, is there a good way to indicate "this is fast"? For example, with T[] or List<T> instead of IEnumerable<T> I know that going from T[i] to T[i+1] will be quick. (Of course, forcing the enumeration to return a list/array could create other performance concerns. List<T> also exposes editable semantics.)

Conversely, would returning IQueryable<T> instead of IEnumerable<T> be a good way to indicate "this is slow"? Or maybe IEnumerable<Task<T>>?

Clients of C have no way of knowning that the IEnumerable<T>s will have dramatically different performance characteristics.

class C
{
   readonly T[] m_data;
   public IEnumerable<T> ThisWillIterateQuickly { get { return m_data; } }

   public IEnumeralbe<T> ThisWillIterateSlowly
   {
      get
      {
         T retval = ... an expensive database call ...;
         yield return retval;
      }
   }

   public IQueryable<T> IsThisBetterForSlow { get { return ThisWillIterateSlowly; } }
   public T[] IsThisAGoodWayForFast { get { return m_data; } }
 }

回答1:


Conversely, would returning IQueryable instead of IEnumerable be a good way to indicate "this is slow"?

No, IQueryable<T> inherent from IEnumerable<T>... and the problem with IEnumerable<T>T is that it could be IQueryable<T> with a a huge side affect when iterating, like query a remote database or something like that.

Funny isn't it?

You probably should be asking about IEnumerable<T> V.S. List<T> which the second one definitely has the data in it, and doesn't need to get it from somewhere else.




回答2:


If you want to guarantee that iteration will not contain any surprises then I agree, expose a T[] - the enumerator for it cannot be overridden as you cannot inherit from arrays. Iteration is also side-effect free, the same cannot be said for IEnumerable<T>.

However, I would disagree that exposing an array expresses this message, which is more important (in my opinion). The performance of something can never really be expressed in code, unless you start naming stuff CheapIteration or ExpensiveIteration.

On the other side of the coin, with an array you simply move the performance problem of on-demand iteration to the point of populating the array. This is guaranteed to hit the performance problem fully as it will be a full iteration of whatever supplies the array contents. In an IEnumerable<T> if iteration stops, so does the performance problem - the fastest code is the code that doesn't run.




回答3:


After thinking about this some more, it seems the problem/question really centers on the behavior/performance of IEnumerator.MoveNext(). Using Visual Studio 2012, I was able to create async versions of IEnumerator and IEnumerable:

public interface IAsyncEnumerator<T> : IDisposable
{
    Task<T> CurrentAsync { get; }
    Task<bool> MoveNextAsync();
    Task ResetAsync();
}

public interface IAsyncEnumerable<T>
{
    IAsyncEnumerator<T> GetAsyncEnumerator();
}

A disadvantage to this approach is there isn't a lot of language support; the above won't work with foreach. But, an extension method can ease the pain:

public static class EnumeratorExtensions
{
    public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
    {
        using (var enumerator = enumerable.GetEnumerator())
        {
            while (enumerator.MoveNext())
                action(enumerator.Current);
        }
    }

    public static async Task ForEachAsync<T>(this IAsyncEnumerable<T> enumerable, Action<T> action)
    {
        using (var enumerator = enumerable.GetAsyncEnumerator())
        {
            while (await enumerator.MoveNextAsync())
                action(await enumerator.CurrentAsync);
        }
    }
}



回答4:


I usually use properties for returning 'quick' enumerations and methods for 'slow'.

Your problem is an argument for using asynchronous approach and design as much as possible. Then it really doesn't matter how long the enumeration takes, as the UI is responsive and the user happy ;-)



来源:https://stackoverflow.com/questions/10934501/what-is-a-good-way-to-to-indicate-an-ienumerable-is-slow-or-fast

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!