有没有办法知道当前的foreach运行而不必:
Int32 i;
foreach
i++;
或者这是我得到的最佳选择?另外,我怎么知道该循环中的最大项目数?我想要做的是在我的表单上的foreach循环期间更新进度条。
这是我到目前为止所做的:
FileInfo[] directoryFiles = (new DirectoryInfo(folderBrowserDialog.SelectedPath)).GetFiles("*.*");
foreach (FileInfo file in directoryFiles)
{
if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden || (file.Attributes & FileAttributes.System) == FileAttributes.System)
continue;
backgroundWorkerLoadDir.ReportProgress(i, file.Name);
System.Threading.Thread.Sleep(10);
}
所以它应该如下,对吗?
for (Int32 i = 0; i < DirectoryFiles.Length; i++)
{
if ((DirectoryFiles[i].Attributes & FileAttributes.Hidden) == FileAttributes.Hidden || (DirectoryFiles[i].Attributes & FileAttributes.System) == FileAttributes.System)
continue;
backgroundWorkerLoadDir.ReportProgress((i / DirectoryFiles.Length) * 100, DirectoryFiles[i].Name);
System.Threading.Thread.Sleep(10);
}
答案 0 :(得分:7)
Foreach是一个相当大的交易,它的底层管道是一个非常简单的仅向前迭代器,它不需要预先知道集合中有多少项。的IEnumerator&LT;&GT;
一般来说,与ProgressBar相比,这是一个相当令人讨厌的不匹配。当您事先知道要迭代的项目数时,您只能有意义地更新标准项目。所以你可以设置它的最大属性。如果 可能,那么您无疑可以访问Count属性并拥有索引器。然后,它允许你使用for()语句,问题解决了。
但是你很不知道有多少项要迭代。例如,典型的dbase查询。由于您无法确定迭代可能需要多长时间,因此进度条上只有一个选项:Style = Marquee。 “我没有死,我正在努力”报告进展的方式。问题解决了。
答案 1 :(得分:6)
使用for
循环代替foreach
。在这种情况下,情况会更好。
像这样使用:
count = DirectoryFiles.Length;
for (int k = 0; k < count; k++)
{
FileInfo file = DirectoryFiles[k];
if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ||
(file.Attributes & FileAttributes.System) == FileAttributes.System)
{
continue;
}
backgroundWorkerLoadDir.ReportProgress(i, file.Name);
System.Threading.Thread.Sleep(10);
}
答案 2 :(得分:2)
不,IEnumerable是不可能的,因为它没有Count / Length属性。而且,您可以轻松想象无限的IEnumerable序列,例如:
private readonly Random rand = new Random();
private IEnumerable<int> GetInfiniteRandomSequence()
{
while(true)
{
yield return rand.Next();
}
}
答案 3 :(得分:1)
这是您最好的选择,因为标准for
循环不适用于不可索引的IEnumerable
。如果您需要知道项目数,请使用Count
属性;如果没有,那么显然你可以提前知道。
答案 4 :(得分:1)
using System.Linq;
for (var i = 0; i < items.Count(); i++)
{
// Update progress bar here.
}
答案 5 :(得分:1)
此问题的基本原则如下:
List<string> numbers = new List<string>() { "one", "two", "three" };
foreach (var num in numbers.Select((value, index) => new { value, index }))
{
Console.WriteLine("Value: {0}, Index: {1}", num.value, num.index);
}
这将在foreach循环中创建一个新的匿名类型,其中包含num变量中的value
和index
。
所以要解决OP中提供的问题:
FileInfo[] directoryFiles = (new DirectoryInfo(folderBrowserDialog.SelectedPath)).GetFiles("*.*");
foreach (FileInfo file in directoryFiles.Select((value, index) => new {value, index}))
{
if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden
||
(file.Attributes & FileAttributes.System) == FileAttributes.System)
continue;
int progress = (file.index / DirectoryFiles.Length) * 100;
backgroundWorkerLoadDir.ReportProgress(progress, file.value.Name);
System.Threading.Thread.Sleep(10);
}