问题描述
这个问题的答案What是的IEnumerable的业绩预期?说,有没有办法知道点儿关于迭代任意IEnumerable的表现。每次迭代可能达到一个数据库或进行网络serivce呼叫;或者它可能只是返回数组/列表中的下一个项目。
鉴于这种情况,有什么好办法来表示:这是快?例如, T []
或名单,其中,T>
而不是的IEnumerable< T>
我知道,从 T [I]
到 T [I + 1]
将要快点。 (当然,迫使枚举返回一个列表/阵列可以创建其他性能方面的问题名单,其中,T>
也暴露出编辑语义)
相反,会返回的IQueryable< T>
而不是的IEnumerable< T>
是一个很好的方法来指示这就是慢?或者,也许的IEnumerable<任务< T>>
C
的客户端没有办法knowning的是,的IEnumerable< T>
旨意有显着不同的性能特点
C类
{
只读T [] M_DATA;
公开的IEnumerable< T> ThisWillIterateQuickly {{返回M_DATA; }}
公共IEnumeralbe< T> ThisWillIterateSlowly
{
得到
{
牛逼RETVAL = ...昂贵的数据库调用...;
得到的回报RETVAL;
}
}
公众的IQueryable< T> IsThisBetterForSlow {{返回ThisWillIterateSlowly; }}
大众T [] IsThisAGoodWayForFast {{返回M_DATA; }}
}
想着这一些之后,看来问题/问题实际上集中在的行为/性能IEnumerator.MoveNext()
。使用的的Visual Studio 2012 的,我能创造的异步版本的IEnumerator
和的IEnumerable
:
公共接口IAsyncEnumerator< T> :IDisposable接口
{
任务< T> CurrentAsync {获得; }
任务<布尔> MoveNextAsync();
任务ResetAsync();
}
公共接口IAsyncEnumerable< T>
{
IAsyncEnumerator< T> GetAsyncEnumerator();
}
这种方法的缺点是没有很多的语言支持;上面会不会与的foreach
工作。但是,扩展方法可以缓解疼痛:
公共静态类EnumeratorExtensions
{
公共静态无效的ForEach< T>(这IEnumerable的< T>枚举,动作< T>动作)
{
使用(VAR枚举= enumerable.GetEnumerator())
{
而(enumerator.MoveNext())
行动(enumerator.Current);
}
}
公共静态异步任务ForEachAsync< T>(这IAsyncEnumerable< T>枚举,动作< T>动作)
{
使用(VAR枚举= enumerable.GetAsyncEnumerator())
{
同时,(等待enumerator.MoveNextAsync())
行动(等待enumerator.CurrentAsync);
}
}
}
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; } }
}
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);
}
}
}
这篇关于有什么好办法来表示一个IEnumerable是&QUOT;缓慢&QUOT;或QUOT;快&QUOT;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!