狛ログ

2013年7月7日日曜日

C# Array.ForEach内でのbreak、continue、return。

オフィス狛 技術部です。

前々回の記事「C#でモダンプログラミング」の続きです。

記事内では、最終的にArray ForEachを利用した繰り返し処理を行っていましたが、
Array ForEachは、繰り返し処理内でのbreak、continue、returnは使用できません。

例えば、以下のような処理があったとします。
int[] nums = new int[] { 1, 3, 4, 9, 12, 14, 15, 19, 20, 23, 28 };

int result = 0;
foreach (int num in nums)
{
    if (num > 20)
    {
        break;
    }
    else
    {
        result += num;
    }
}

ソートされた配列内で、値が20以下の場合、値を足し込み、20より大きい値が存在した時点で、
繰り返し処理を終了しています。

これをArray.ForEachで書き換えて、以下のようにするとコンパイルエラーになります。
  int[] nums = new int[] { 1, 3, 4, 9, 12, 14, 15, 19, 20, 23, 28 };
  int result = 0;
  Array.ForEach<int>(nums, num =>
      {
          if (num > 20)
          {
              break;        //コンパイルエラー
          }
          else
          {
              result += num;
          }
      }
  );

では、どうすれば良いのか?
方法は色々あると思いますが、「配列内の20以下の値を足し込む」では無く、
「配列から20以下の値を抽出し、抽出した値を全て足し込む」で対応してみます。

匿名メソッド(ラムダ式)では以下のようになります。
int[] nums = new int[] { 1, 3, 4, 9, 12, 14, 15, 19, 20, 23, 28 };
int[] findnums = Array.FindAll(nums, num => num <= 20);
int result = 0;
Array.ForEach(findnums, num => result += num);

LINQでは以下の通りです。
int[] nums = new int[] { 1, 3, 4, 9, 12, 14, 15, 19, 20, 23, 28 };
var query = from num in nums
            where num <= 20
            select num;
int[] findnums = query.ToArray();
int result = 0;
Array.ForEach(findnums, num => result += num);

ちなみに、今回はArray.ForEachに視点を当てているので、
匿名メソッドやLINQも冗長な書き方になっています。
今回のプログラムの仕様(条件判断して数値を足し込む)を満たしたいのであれば、
通常は匿名メソッドやLINQの集計演算子(SUM)を使用します。