Подтвердить что ты не робот

Как вы находите последний цикл в "Для каждого" (VB.NET)?

Как я могу определить, находится ли я в последнем цикле выражения For Each в VB.NET?

4b9b3361

Ответ 1

Как правило, коллекции, на которых вы можете выполнить For Each, реализовать интерфейс IEnumerator. Этот интерфейс имеет только два метода: MoveNext и Reset и одно свойство Current.

В основном, когда вы используете For Each в коллекции, он вызывает функцию MoveNext и считывает возвращаемое значение. Если возвращаемое значение равно True, это означает, что в коллекции есть допустимый элемент, а элемент возвращается через свойство Current. Если в коллекции больше нет элементов, функция MoveNext возвращает False, и итерация завершается.

Из приведенного выше объяснения ясно, что For Each не отслеживает текущую позицию в коллекции, и поэтому ответ на ваш вопрос - короткий No.

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

For Each item in Collection
    If item Is Collection.Last Then
        'do something with your last item'
    End If
Next

Ответ 2

Вероятно, было бы проще просто использовать цикл For вместо ForEach. Но, аналогично, вы могли бы держать счетчик внутри своего цикла ForEach и видеть, равно ли ему yourCollection.Count - 1, то вы находитесь в последней итерации.

Ответ 3

С помощью foreach вы не можете знать это, пока не станет слишком поздно (т.е. вы вышли из цикла).

Заметьте, я предполагаю, что вы используете что-то, где у вас есть только интерфейс IEnumerable. Если у вас есть список, массив и т.д., То следуйте другим ответам здесь, где используется .Count или аналогично, чтобы узнать, сколько там элементов, и, следовательно, вы можете отслеживать, где вы находитесь в коллекции.

Однако, с помощью только IEnumerable/IEnumerator, нет никакого способа узнать наверняка, или нет, если вы используете foreach.

Если вам нужно это знать, используйте IEnumerable самостоятельно, что и делает foreach.

Ниже приведено решение для С#, но должно легко перевести его на VB.NET:

List<Int32> nums = new List<Int32>();
nums.Add(1);
nums.Add(2);
nums.Add(3);

IEnumerator<Int32> enumerator = nums.GetEnumerator();
if (enumerator.MoveNext())
{
    // at least one value available
    while (true)
    {
        // make a copy of it
        Int32 current = enumerator.Current;

        // determine if it was the last value
        // if not, enumerator.Current is now the next value
        if (enumerator.MoveNext())
        {
            Console.Out.WriteLine("not last: " + current);
        }
        else
        {
            Console.Out.WriteLine("last: " + current);
            break;
        }
    }
}
enumerator.Dispose();

Это напечатает:

not last: 1
not last: 2
last: 3

Хитрость заключается в том, чтобы взять копию текущего значения, а затем попросить перечислитель попытаться перейти к следующему. Если это не удается, копия, которую вы сделали, действительно была последним значением, в противном случае больше.

Ответ 4

Короткий ответ: вы не можете

Длинный ответ: в семантике оператора For Each нет ничего, что позволяет определить, запускаете ли вы первую, последнюю или какую-либо конкретную итерацию.

Для каждого встроен интерфейс IEnumerable и IEnumerable < > , и поведение зависит от реализации, которую вы вызываете. Это действительно, хотя и запутанно, для коллекции, которую вы итерируете, чтобы возвращать элементы в другом порядке каждый раз. К счастью, List < > не делает этого.

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

Легче было бы обнаружить первую итерацию (скажем, через логическое), а затем сделать что-то другое.

Пример (С#, но VB будет похож):

StringBuilder result = new StringBuilder();
bool firstTime = true;
foreach(string s in names)
{
    if (!firstTime)
    {
        result.Append(", ");
    }

    result.Append(s);
    firstTime = false;
}

Ответ 5

Проверьте, является ли элемент последним элементом контейнера.

Почему вы хотите это сделать?
Вы можете просто разместить инструкции после цикла. (Что вы выполняете на последнем элементе)

Ответ 6

Было бы проще использовать цикл For вместо ForEach, однако вы могли бы сделать что-то вроде

If item.Equals(itemCollection(itemCollection.Count)) Then
    ...
End If

внутри вашего цикла ForEach... Предполагая, что объект правильно переопределил метод Equals.

Это, вероятно, гораздо более ресурсоемкий, чем просто использование цикла For или отслеживание текущего индекса в отдельной переменной.

Я не уверен, что это правильный синтаксис, я долгое время использовал VB.

Ответ 7

Используя стандартный цикл "Для каждого", вы не можете. Цель цикла "для каждого" заключается в том, чтобы вы могли сосредоточиться на данных вместо базовой коллекции.

Ответ 8

Я возвращаюсь на этот пост, поэтому решил сесть и подумать об этом, и я придумал это:

    For Each obj In myCollection
        Console.WriteLine("current object: {0}", obj.ToString)

        If Object.ReferenceEquals(obj, myCollection.Last()) Then
            Console.WriteLine("current object is the last object")
        End If
    Next

Вы даже можете уменьшить оператор If...Then...End If до одной строки, если хотите. Я не уверен, что вызов .Last() на каждой итерации сильно влияет на производительность, но вы всегда можете назначить ее переменной вне цикла, если это то, что заставляет вас спать по ночам.

Ответ 9

этот пример кода может помочь

For Each item in Collection
  If ReferenceEquals(Collection.Item(Collection.Count - 1), item) Then
    'do something with your last item'
  End If
Next

Ответ 10

Если вы привязаны к IEnumerable. Вы должны находиться внутри цикла foreach? Если нет, вы можете объявить переменную непосредственно перед циклом foreach. Установите его во время цикла. Затем используйте его после цикла (если его не null)

Ответ 11

Ну, есть немного обходных решений Предположим, вы работаете с CheckBoxList

Тогда этот пример кода может помочь:

Dim count As Integer = 0
Dim totalListCount As Integer = CheckBoxList.Items.Count()
For Each li In CheckBoxList.Items
         count += 1
           // This is the Last Item
      If count = totalListCount THEN
          // DO Somthing.....
      END IF
NEXT     

Ответ 12

вот простая вещь, я не знаю, является ли она политически корректной, но она работает

for each item in listOfThings
   if(item = listOfThings.last)then 
       'you found the last loop
   end if
next