Home > C# > C# 学び直し

C#で使う繰り返し構文

新規作成日 2017-02-21
最終更新日

繰り返し構文は、プログラムを作成する際に頻繁に使用します。自分なりの使用パターンを確立するまでは、どの構文を使用するべきかよく考える必要があります。

コンピュータプログラムの処理は、以下の3つに分類されます。

  • 順次処理(じゅんじしょり)
  • 分岐処理(ぶんきしょり)
  • 繰り返し処理(くりかえししょり)

繰り返し処理は、同じ処理を何度も繰り返すときに使用します。ループ処理、反復処理とも呼ばれています。

具体的には、以下の場合に使用します。

  • 対象を変えて同じ処理を行う
  • 条件に合うまで同じ処理を行う

.Net言語では、対象を変えて同じ処理を行う場合は、foreach構文が、条件に合うまで同じ処理を行う場合は、for構文が使われることが多いです。

繰り返すコレクションを操作する繰り返し処理

配列やListなどの対象が含まれるコレクション内の項目に1つ1つを処理する場合は、forreach構文を使用すると便利です。

foreach(型 変数名 in コレクション)
{
...
}

構文から判断すると、コレクション内の全ての項目に対してループを実行することから、ループ内で、コレクション内の項目を操作できるように思えます。しかし、その繰り返し処理の中で、処理する対象のコレクションに項目を追加したり、削除する操作を行いたい場合、forreach構文は使用できません。すなわち、forreach構文は、繰り返し処理の間、対象となるコレクションを変更しない場合でのみ使用できます。

繰り返し対象のコレクションを、その繰り返し処理の間に、追加や削除したい場合、その操作を行わない方法を考えるか、別の繰り返し方法を考える必要があります。つまり、繰り返しを始める段階で、繰り返す内容が確定していない処理です。

関連サイト

コレクションを繰り返す際、処理した項目と処理していない項目を区別する必要があります。それをイテレーター(反復子)と呼びます。このイテレーターにどこまで処理したかの情報を格納して対処します。

for構文を考えると理解しやすいと思います。

for(初期化式; 条件式; 更新式)
  反復を行いたい文
    for(int x=1; x<=9; ++x) // xを1~9まで、1ずつ増やして繰り返し
    {
            Console.Write(x + "\n");
    }

この場合、xがイテレーターになります。

ループの中で、xを変更してしまうと処理したものと処理しないものがわからなくなってしまうのが原因です。

foreach構文は、for構文を使う特定の場合に、条件式を自動で与える構文と考えることができます。条件式の定義の設定や変更時の勘違いや修正漏れは、頻繁に発生するので、foreach構文が利用できる場合は積極的に利用することが推奨されていています。

繰り返し対象のコレクションを、その繰り返し処理の間に、追加や削除したい場合、処理した項目とこれから処理する項目をプログラム中で管理すればうまくいきそうです。2つの方法を考えることができます。

  • 処理したい項目に、処理されたか、処理されていないかのフラグを追加する
  • 処理するたびに、繰り返し対象のコレクションから、処理した項目を削除する

このように考えると、繰り返し処理ではなく、作業項目リスト内の全ての項目を処理するプログラムと考えることができます。

処理する項目のリストを無くなるまで処理する場合は、条件を指定しないfor構文、あるいは、do構文やwhile構文を使用します。

条件を指定しないfor構文

条件を指定しないfor構文は、無限ループになります。ループの内部で終了条件を確認し、ループを抜ける処理を記述して使用します。

for(;;;)
{
…
}

while構文

while構文は、ループの先頭で条件式の評価を行います。そのため、ループの処理が1回も実行されない可能性もあります。

while(条件文)
{
…
}

do-while構文

do-while構文は、ループの末尾で条件を評価します。そのため、ループの処理は、必ず1回は実行されます。

do
{
…
}
while(条件式);

while構文とdo-while構文は、条件式を省略したfor構文に、ループを抜けるための条件式を追加した構文と考えることができます。

ループを制御するための構文には、breeak文とcontinue文があります。

  • breeak文を使うと、ループから抜け、ループ外の処理に移ることができます。
  • continue文を使うと、ループの途中から、ループの先頭に移動することができます。

無限ループを使用する際は、プログラムミスで、ループが終了しない可能性があるので、キー入力を受け付けてループを終了するコードを追加しておくことをお勧めします。

Console.Read();

ループ内で使用するクラスは、ループ外でインスタンスを作成する

ループ内で使用するクラスは、ループに入る前に、インスタンスを作成します。ループ内で、インスタンスを作成するとループのたびにインスタンスを作成する事になり、メモリを無駄に使用することで、処理速度が遅くなる原因になります。同じ理由で、変数の宣言もループの中で行うことは、避けたほうが無難です。

LINQ

C#では、ループで処理する内容によってはLINQ構文を使用して、条件に一致する項目に対して、処理を行う方法があります。全ての場合に使えるわけではありませんが、処理する内容によっては、大幅にコードが削減できます。

このエントリーをはてなブックマークに追加

Home PC C# Illustration

Copyright (C) 2011 Horio Kazuhiko(kukekko) All Rights Reserved.
kukekko@gmail.com
ご連絡の際は、お問い合わせページのURLの明記をお願いします。
「掲載内容は私自身の見解であり、所属する組織を代表するものではありません。」