表明IEnumerable是"慢"还是"快"的好方法是什么?

Ðаn*_*Ðаn 7 .net performance ienumerable iqueryable

这个问题的答案是什么了IEnumerable预期的性能?说没有办法知道迭代任意IEnumerable的性能.每次迭代都可以访问数据库或进行Web服务调用; 或者它可能只返回数组/列表中的下一个项目.

鉴于此,是否有一种很好的方式来表明"这很快"?例如,用T[]List<T>代替IEnumerable<T>我知道从哪里T[i]开始T[i+1]会很快.(当然,强制枚举返回列表/数组可能会产生其他性能问题. List<T>还会暴露可编辑的语义.)

相反,返回IQueryable<T>而不是IEnumerable<T>一个表明"这很慢"的好方法?或许IEnumerable<Task<T>>

客户C无法知道IEnumerable<T>s将具有截然不同的性能特征.

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; } }
 }
Run Code Online (Sandbox Code Playgroud)

Ðаn*_*Ðаn 1

经过更多思考后,问题似乎真正集中在 的行为/性能上IEnumerator.MoveNext()。使用Visual Studio 2012,我能够创建IEnumerator和的异步版本IEnumerable

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

public interface IAsyncEnumerable<T>
{
    IAsyncEnumerator<T> GetAsyncEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点是没有太多的语言支持;以上不适用于foreach. 但是,扩展方法可以减轻痛苦:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)