2011-01-01 3 views
1

Есть ли способ узнать текущий пробег в Еогеасп без должны:Текущий индекс цикла Еогеасп

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); 
    } 
+2

Могли бы вы вставить текущий код, в том числе декларации для коллекции, вы итерации? – Reinderien

+2

Пожалуйста, напишите какой-нибудь реальный код, а не псевдокод. –

+0

Каков тип массива/коллекции u? –

ответ

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); 
} 
+0

Прошу прощения, но это не работает для 'ICollection'. :( – Mehrdad

+0

@Lambert хорошая точка. Не уверен, что ОП пытается проскочить. –

+0

Пример, который вы указали, выглядит как цикл 'for' для меня ... –

1

Это ваш лучший вариант, потому что стандартные for петли не работают на IEnumerable с, не индексируемых. Если вам нужно знать количество предметов, используйте свойство Count; если их нет, то, по определению, вы не можете заранее знать.

1
using System.Linq; 

for (var i = 0; i < items.Count(); i++) 
{ 
    // Update progress bar here. 
} 
+0

Это не работает для 'ICollection'. – Mehrdad

+0

Я добавил директиву using и изменил метод Count на метод, который будет работать для контейнеров ICollection. –

+0

Теперь это только для .NET 3.5 + ... :) и, кстати, это очень * медленно, потому что я не думаю, что компилятор JIT может видеть достаточно далеко, чтобы оценивать только элементы items.Count(), поэтому он оценим e это несколько раз, что приводит к резкому снижению скорости для некоторых коллекций. Вам нужно будет кэшировать переменную в начале. :) – Mehrdad

7

Foreach является довольно большим делом, лежащая в его основе сантехники является очень простым однонаправленным итератором, который не требует того, чтобы фронт, сколько элементов в коллекции знает. IEnumerator <>.

В целом это довольно неприятное несоответствие с ProgressBar. Вы можете только осмысленно обновить стандартный, когда знаете, сколько элементов вы итерации. Таким образом, вы можете установить его свойство Maximum. Если возможно , то есть, то вы, несомненно, имеете доступ к свойству Count и имеете индекс. Что затем позволяет использовать инструкцию for(), решить проблему.

Но довольно распространено, что у вас нет идеи, сколько предметов есть для итерации. Типично с запросами dbase, например. Поскольку вы не можете узнать, сколько времени потребуется для повторения, у вас есть только одна опция на индикаторе выполнения: Style = Marquee. «Я не умер, я работаю», способ сообщить о прогрессе. Задача решена.

2

Нет, это невозможно для IEnumerable, поскольку оно не имеет свойства Count/Length. Кроме того, вы можете легко представить себе бесконечную IEnumerable последовательность, как:

private readonly Random rand = new Random(); 
private IEnumerable<int> GetInfiniteRandomSequence() 
{ 
    while(true) 
    { 
     yield return rand.Next(); 
    } 
} 
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); 
} 

Это создаст новый анонимный тип внутри цикла Еогеасп, который содержит value и index в переменной num.

Итак, чтобы решить эту проблему, представленную в 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); 
} 
Смежные вопросы