C#. Подробнее о циклах

Циклы в C#

В этой статье я кратко и простым языком расскажу о том, как можно использовать циклы в C# более эффективно и гибко! Основная информация по циклам в C# представлена в уроках базового курса (Управление ходом выполнения программы и Циклы с заранее неизвестным количеством повторений). Тем не менее, для более гибкого использования возможностей языка, необходимо знать некоторые нюансы, о которых я сейчас и расскажу. В упомянутых выше уроках, я рассказывал циклах с заранее известным количеством итераций (повторений) — циклах for. Так же, были рассмотрены циклы с заранее неизвестным количеством повторений — циклы while и dowhile. В этой статье, я расскажу о таком цикле как foreach и об операторах принудительного завершения циклов, досрочного перехода к следующей итерации цикла и т.п.

И так, для чего же нужен оператор цикла foreach? Знаете, на самом деле он не является незаменимым, он относится скорее к роскоши. Именно оп этой причине я не рассказывал о нём в базовом курсе. Оператор foreach позволяет перебрать все элементы массива, списка (или другой коллекции), очевидно, что эту операции можно проделать и используя оператор for, но в большинстве случаев, для выполнения данной задачи, Вы будите использовать именно foreach. Как им пользоваться я покажу на примере, представим, что нам нужно перебрать все элементы целочисленного массива вывести значение каждого в консоль, выглядеть на практике, это примерно будет так:

int[] someArray = new int[20];

//Перебор всех элементов массива
foreach (int tmpElem in someArray)
{
    Console.WriteLine(tmpElem);
}

Как видно из примера, использование оператора foreach чуть проще чем оператора for. Его особенности заключаются в том, что после ключевого слова foreach, в круглых скобках, мы указываем «временную переменную» (в нашем случае, это «int tmpElem»), совпадающую по типу (или хотя бы приводимую)  с типом элементов массива. Такую переменную, иногда называют итератором цикла.  Так вот после этой переменной следует ключевое слово in, а за ним — сама коллекция (в нашем случае массив «someArray»), все элементы которой нужно перебрать.

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

Еще одна особенность переменной-итератора заключается в том, что при каждой итерации (при каждом повторе цикла), эта переменная автоматически получает значение текущего элемента коллекции (т.е. на первой итерации, значение переменной-итератора будет равно значению первого элемента, на второй — второго, на последней — последнего), но это значение может быть использовано только для «чтения». Т.е. вот так уже сделать не получится:

int[] someArray = new int[20];

//Перебор всех элементов массива
foreach (int tmpElem in someArray) 
{ 
    tmpElem = 0; //Ошибка компиляции 
} 

Таким образом, используя оператор foreach, мы уходим от работы с индексами, но получаем и побочный эффект… Плюс еще, во время выполнения цикла foreach не стоит изменять саму коллекцию, например, удалять из списка элементы!

Однако, даже при переборе всех элементов некой коллекции, мы может понять, что пора прервать цикл именно сейчас, на этой итерации а не на последней, так как же это сделать? Используя циклы while или for где мы в любое время могли искусственно подставить контролируемое значение, под условие завершения цикла и цикл бы прервался на текущей итерации. Но в цикле foreach нет явной проверки каких либо условий… Но выход есть и тут, в языке C# есть ключевое слово break, которое можно использовать в теле цикла, прерывая его тем самым в нужной точке. Например, можно завершить цикл, в момент нахождения отрицательного значения элемента какого-то массива:

//Перебор всех элементов массива someArray
foreach (int tmpElem in someArray)
{
    //Если текущий элемент массива меньше нуля
    if (tmpElem < 0)
        break; //Прервать цикл на этом же месте

    Console.WriteLine(tmpElem);
}

Вот так всё просто! Но это еще не все, мы можем не просто прервать цикл (в приведенном выше примере, после выполнения оператора break) выполнение программы перешло бы к следующему за закрывающей фигурной скобкой цикла оператору (в нашем примере его нет), но на может понадобиться завершить не только сам цикл, но и, например, метод, в котором выполняется цикл. Делается это так же просто, вместо ключевого слова break используется ключевое слово return:

public void SomeMethod()
{
//Какие-то операторы

//Перебор всех элементов массива someArray
foreach (int tmpElem in someArray)
{
    //Если текущий элемент массива меньше нуля
    if (tmpElem < 0)
        return; //Прервать не только цикл на этом же месте, но и метод SomeMethod

    Console.WriteLine(tmpElem); 
} 

//Какие-то другие операторы } 

А бывают на оборот, случаи, когда нужно прервать, точнее пропустить остаток только текущей итерации, например, если элемент массива равен нулю, то не обрабатывать его и перейти к следующей итерации. Конечно, такую задачу можно решить используя условный оператор ifelse, но есть и еще один путь, использовать ключевое слово continue, которое автоматически переведет цикл к следующей итерации (и такой подход бывает значительно элегантнее). Использовать его можно так:

//Перебор всех элементов массива someArray
foreach (int tmpElem in someArray)
{
    //Если текущий элемент массива равен нулю
    if (tmpElem == 0)
        continue; //Перейти сразу к следующей итерации цикла

    Console.WriteLine(tmpElem);
}

Вот такие вот нюансы использования циклов в C#. Иногда, они могут быть очень полезными, и сделать Ваш код значительно более легко читаемым и сопровождаемым.

Добавить комментарий