什么是指示一个IEnumerable是“慢”或“快”的好办法?(What is a good way

2019-09-17 21:18发布

这个问题的答案是什么了IEnumerable预期的性能? 说也没有办法了解迭代任意IEnumerable的性能点儿。 每次迭代可以打一个数据库或进行网络电话serivce; 或者它可能只是一个数组/列表中返回的下一个项目。

鉴于此,有表示“这是快”的好办法? 例如,用T[]List<T>代替IEnumerable<T>我知道从去T[i]T[i+1]会很快。 (当然,迫使枚举返回一个列表/阵列可以创建其他性能问题。 List<T>也暴露可编辑的语义。)

反之,将返回IQueryable<T>代替IEnumerable<T>是表示“这是慢”的好办法? 或者,也许IEnumerable<Task<T>>

的客户C没有knowning所述的方式IEnumerable<T>旨意具有显着不同的性能特性。

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; } }
 }

Answer 1:

相反,会返回IQueryable的,而不是IEnumerable的是,表示“这是慢”的好办法?

不, IQueryable<T>从固有IEnumerable<T> ......与问题IEnumerable<T>T的是,它可能是IQueryable<T>与迭代时,像查询远程数据库或类似的东西AA巨大的侧影响。

有趣的是不是?

你可能要问IEnumerable<T> VS List<T>这第二个,绝对有它的数据,并不需要从别的地方得到它。



Answer 2:

如果你想保证迭代将不包含任何意外,那么我同意,露出T[] -它枚举不能被重写,因为你不能从数组继承。 迭代也可以自由的副作用,同样不能说对IEnumerable<T>

不过,我不同意,露出一个数组表示这个消息,这是更重要的(在我看来)。 事物的性能从来没有真正在代码中表示,除非你开始命名的东西CheapIterationExpensiveIteration

在硬币的另一面,有一个数组,你只需移动点播迭代的性能问题,以填充阵列的点。 这是保证充分击中性能问题,因为这将是任何供应数组内容进行完整的迭代。 在一个IEnumerable<T>如果迭代停止时,也是如此性能问题-最快代码是不运行的代码。



Answer 3:

思考这个多一些之后,看来问题/问题实际上集中在行为/性能IEnumerator.MoveNext() 使用Visual Studio 2012,我能创造的异步版本IEnumeratorIEnumerable

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

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

这种方法的缺点是没有很多的语言支持; 上述不会工作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);
        }
    }
}


Answer 4:

我通常使用属性返回“快”枚举和方法“缓慢”。

你的问题是使用异步方法和设计尽可能的说法。 然后,它其实并不重要枚举需要多长时间,作为UI响应和用户快乐;-)



文章来源: What is a good way to to indicate an IEnumerable is “slow” or “fast”?