Новичок C#: узнайте индекс в foreach блоке

Аналогия ? Я дам ему сильный удар... Ваш стерео Проигрывателя компакт-дисков бесполезен без CD с музыкой на нем... (Это зависит от CD). Если бы они создали Проигрыватели компакт-дисков с CD уже в нем, это стало бы скучным очень быстро...

, Таким образом, они создают их так, можно "ввести" CD, (от которого он зависит) в плеер. Тем путем можно ввести различный каждый раз и получить "различное" поведение (музыка), зависящая, на котором Вы вводите.

единственное требование - то, что CD должен быть совместим с интерфейс определенный плеером. (Вы не можете проигрывать диск синего луча в проигрывателе компакт-дисков 1992.)

18
задан Ruben Bartelink 8 April 2013 в 20:06
поделиться

9 ответов

Нет, нет.

Это случай, когда вам лучше использовать базовый цикл for

for(int i = 0; i < y.Count; i++)
{
}

, а не для каждого цикла

EDIT : В ответ на разъяснения спрашивающих.

Если вы выполняете итерацию через перечислитель без свойства размера (такого как длина или количество), то ваш подход настолько ясен, насколько это возможно.

Second Edit
Учитывая меня, druthers, я бы взял ответ Марка, используя select, чтобы сделать это в наши дни.

22
ответ дан 30 November 2019 в 06:04
поделиться

Вопреки некоторым другим ответам, я был бы совершенно счастлив смешать foreach со счетчиком (согласно коду в вопросе). Это сохраняет вашу способность использовать IEnumerable [] вместо того, чтобы требовать индексатора.

Но если хотите, в LINQ:

    foreach (var pair in y.Select((x,i) => new {Index = i,Value=x})) {
        Console.WriteLine(pair.Index + ": " + pair.Value);
    }

(встречный подход в вопросе намного проще и более эффективно, но приведенное выше должно лучше соответствовать нескольким сценариям, таким как Parallel.ForEach).

24
ответ дан 30 November 2019 в 06:04
поделиться

Нет, на самом деле не существует неявного «счетчика» внутри цикла foreach.

Цикл foreach за крышками создает IEnumerator и затем перебирает элементы один за другим, вызов метода .MoveNext () в интерфейсе IEnumerator.

В интерфейсе IEnumerator нет (к сожалению?) Переменной счетчика - только методы .Reset () и .MoveNext () и свойство Current (возвращающее текущий элемент)

Marc

5
ответ дан 30 November 2019 в 06:04
поделиться

Ваш подход настолько ясен, насколько это возможно. Однако вы можете отметить, что часть i ++ на самом деле не связана с основными функциями цикла (без учета количества / длины / других параметров). Таким образом, вы можете рассмотреть возможность перемещения и метода writeDebug и i ++ в отдельный метод / класс (updateProgress ()) и просто вызвать его из цикла.

3
ответ дан 30 November 2019 в 06:04
поделиться

Foreach использует интерфейс IEnumerator , который имеет свойство Current, а также методы MoveNext и Reset.

Current возвращает объект, на котором в данный момент находится Enumerator. , MoveNext обновляет Current до следующего объекта.

В foreach нет концепции индекса, и мы не можем быть уверены в порядке перечисления.

Вам придется либо применить переменную для этого или используйте вместо этого цикл for.

Я бы предпочел использовать for lop вместо того, чтобы отслеживать это с помощью переменной.

2
ответ дан 30 November 2019 в 06:04
поделиться

Нет, это невозможно сделать внутри цикла foreach. В этом случае вы должны использовать цикл for или, как вы упомянули, явно создать переменную для подсчета.

1
ответ дан 30 November 2019 в 06:04
поделиться

Это зависит от фактического типа перечислителя, для которого вы используете цикл. Однако во многих коллекциях есть метод IndexOf

        ArrayList arrayList = new ArrayList();

        arrayList.Add("A");
        arrayList.Add("B");
        arrayList.Add("C");

        foreach (string item in arrayList)
        {
            int i = arrayList.IndexOf(item);
        }

. Конечно, это не работает, если в вашем списке есть повторяющиеся элементы. Это тоже не самое эффективное решение. Я бы остановился на вашем исходном и просто оставил бы переменную, чтобы отслеживать индекс.

1
ответ дан 30 November 2019 в 06:04
поделиться

Я не знаю, что именно означает «y» в вашем примере, но, возможно, вы могли бы написать это так:

  foreach (var x in y.WithIndex())
  {
    WriteDebug(String.Format("Step: {0}", x.Index));
  }

При условии, что вы добавляете в свой проект следующий класс расширения:

  public static class Extensions
  {
    public static IEnumerable<IndexValuePair<T>> WithIndex<T>(this IEnumerable<T> source)
    {
      if (source == null) throw new ArgumentNullException("source");
      var position = 0;
      foreach (T value in source)
      {
        yield return new IndexValuePair<T>(position++, value);
      }
    }
  }

  public class IndexValuePair<T>
  {
    public IndexValuePair(Int32 index, T value)
    {
      this.index = index;
      this.value = value;
    }

    private readonly Int32 index;
    public Int32 Index
    {
      get { return index; }
    }

    private readonly T value;
    public T Value
    {
      get { return value; }
    }
  }

HTH, Деян

1
ответ дан 30 November 2019 в 06:04
поделиться

Если вам абсолютно необходим индекс, используйте вместо него традиционный цикл for.

for (int i = 0; i < y.Count; i++)
{
    WriteDebug("Step: "+i.ToString());    
}
0
ответ дан 30 November 2019 в 06:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: