首先,这是不可能的
IEnumerable<T>
因为无法获得元素的数量。为了实现这一点,您应该使用任何实现
ICollection<T>
相反,这样你可以得到
number of items
.
其次,你不能真正使用现有的
Select
方法(如果没有一些黑客攻击的话),但您可以编写自己的方法。下面是我在投影期间为列表中的每个元素调用的操作。
首先是一个类,用于保存当前进度的详细信息。
public class SelectProgress
{
public decimal Percentage { get; set; }
public TimeSpan TimeTaken { get; set; }
public TimeSpan EstimatedTotalTime { get; set; }
}
和习俗
选择
方法:
public static IEnumerable<TResult> Select<TSource, TResult>(
this ICollection<TSource> source,
Func<TSource, TResult> selector,
Action<SelectProgress> timeRemaining)
{
Stopwatch timer = new Stopwatch();
timer.Start();
var counter = 0;
foreach (var element in source)
{
yield return selector(element);
counter++;
timeRemaining?.Invoke(new SelectProgress
{
Percentage = counter/(decimal)source.Count,
TimeTaken = timer.Elapsed,
EstimatedTotalTime =
TimeSpan.FromTicks(timer.Elapsed.Ticks/counter * source.Count)
});
}
}
这样称呼它:
var list = Enumerable.Range(1, 20).ToList();
var results = list.Select(
i =>
{
Thread.Sleep(1000);
return i.ToString();
},
p => Console.WriteLine(
$"{p.Percentage:P2}: Taken: {p.TimeTaken}, Total: {p.EstimatedTotalTime}"))
.ToList();
此代码将生成如下输出:
5.00%: Time taken: 00:00:01.0007261, Estimated total: 00:00:20.0158420
10.00%: Time taken: 00:00:02.0015503, Estimated total: 00:00:20.0155100
15.00%: Time taken: 00:00:03.0017421, Estimated total: 00:00:20.0116180
<snip>
90.00%: Time taken: 00:00:18.0101580, Estimated total: 00:00:20.0112860
95.00%: Time taken: 00:00:19.0103062, Estimated total: 00:00:20.0108480
100.00%: Time taken: 00:00:20.0107314, Estimated total: 00:00:20.0107320