Разве мы не можем использовать оператор break в лямбде (C # 3.0) - PullRequest
4 голосов
/ 18 мая 2010

Рассмотрим это

List<int> intList = new List<int> { 1, 2, 3, 4, 5, 6 };

            int j = 0;
            intList.ForEach(i =>
                {
                    if (i.Equals(1))
                    {
                        j = i;
                        break;
                    }
                }
            );

Ошибка выброса: Нет замкнутого контура, из которого можно разорвать или продолжить

Но ниже работает

foreach(int i in intList)
{
j = i; break;
}

Почему так. Я делаю какую-либо ошибку.

Спасибо

Ответы [ 5 ]

6 голосов
/ 18 мая 2010

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

3 голосов
/ 18 мая 2010

Риск быть урезанным за то, что он "выходит за рамки вопроса", я собираюсь спросить, что это за ОП, которую действительно пытается выполнить.

Код, о котором идет речь, пытается определить, существует ли целое число (1) где-либо в списке. Но мне кажется ясным, что приведенный выше код является просто демонстрацией, а не реальной проблемой.

Использование «ForEach» для итерации по списку, чтобы определить, есть ли что-то в списке, является неправильным способом сделать это. Вместо этого лучше использовать одну из множества функций «Найти».

Например, вместе с исходным кодом ОП:

 j = intList.Find(i => i.Equals(1));

Это будет в точности то же самое, что и предложенный выше код. Он будет перебирать список (и, если возможно), возвращать значение, совпадающее с лямбда-выражением, в «j» и прерываться раньше.

 intList.Exists(i => i.Equals(1));

эффективно сделает то же самое. Он будет перебирать список и возвращать значение ИСТИНА, если сможет найти, существует ли 1, и рано ли "сломаться". (иначе он перебирает весь список и возвращает FALSE.)

 intList.FindIndex(i => i.Equals(1));

Возвращает позицию индекса первого экземпляра, которая соответствует лямбде. (снова, если возможно, рано)

 intList.FindAll(i => i.Equals(1));

Возвращает подсписок всех элементов в intList, которые соответствуют лямбда-выражению. (естественно, это должно повторяться по всему списку, независимо от ...)

Новичок: Есть ли причина, по которой вы не можете использовать ни один из этих встроенных методов? Просто любопытно, как я хотел бы помочь.

Приветствие.

0 голосов
/ 18 мая 2010

Вы можете использовать методы расширения SkipWhile() и Take(), чтобы имитировать то, что вы делаете, но это не хорошо или не читабельно ...

public void SO2857489()
{
    var intList = new List<int> {1, 2, 3, 4, 5, 6};
    var j = 0;
    intList.SkipWhile(i => i != 1).Take(1).ToList().ForEach(i => j = i);
    Console.WriteLine(j);
}

Здесь SkipWhile() выполняет работу вашего оператора if (i.Equals(1)), а Take(1) выполняет работу break. Как я уже сказал, это не красиво.

0 голосов
/ 18 мая 2010

Оператор break работает только в той же области действия, что и оператор foreach. Лямбда запускает новую область действия функции, поэтому разрыв не работает.

0 голосов
/ 18 мая 2010

Метод ForEach не является действительным циклом foreach. Вы можете смоделировать эффект, бросив исключение внутри лямбды и перехватывая его вне вызова на ForEach.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...