連載:[完全版]究極のC#プログラミング

Chapter7 ラムダ式(後編)

川俣 晶
2009/11/02

7.7 ラムダ式の使用例

 ここまでのサンプルコードの大多数は、あくまで構文や機能を説明するもので、必ずしもラムダ式を使用しなくても書けるものが多かった。最後に、ある程度実用性のあるラムダ式の使用例をお見せしよう。

 ここでは、整数の配列の各要素を入力とし、その値で割り算を実行して結果を出力するプログラムを作成する。ここで割り算を使ったのは、入力として受け付けられない値(0)が存在するからである(つまり、このサンプルコードは不正な入力値が存在する事例一般に応用できる可能性がある)。

 このプログラムは入力が0の場合は、その旨を出力して終了しなければならない。この意図をラムダ式抜きで記述するとしたら、どのように書くだろうか?

 この点を考える際のポイントは2つある。

  • 計算を行うループ内で値の0チェックを行うと、計算が始まった後で中断が発生する。つまり、計算値とエラーメッセージの双方が出力されてしまう可能性がある
  • 計算値を出さずにエラーメッセージを出すには、計算ループよりも手前に0チェックのためのループを設ける必要がある。しかし、それを書くとループが2つになって冗長すぎる

 つまり、どちらの方法もデメリットを抱えている。筆者であれば、「計算開始前にチェックを完了すべき」という要求が存在しなければ、冗長さを除去するほうが重要だと考え、ループ内での判定のほうを選ぶ(リスト7.18参照)。

using System;

class Program
{
  static void Main(string[] args)
  {
    int[] a = { 1, 2, 0 };

    foreach (int n in a)
    {
      if ( n == 0 )
      {
        Console.WriteLine("テストデータに0が含まれています。");
        return;
      }
      Console.WriteLine(100 / n);
    }
    // 出力:
    // 100
    // 50

     // テストデータに0が含まれています。
  }
}
リスト7.18 ループ内で判定する場合

 しかし、ラムダ式を使用してよければ、まったく別個の答えが出せる。配列の要素がすべて特定の条件を満たしているかを調べるだけなら、メソッド呼び出し1つとシンプルなラムダ式1つでケリがつくからだ。これは、読みやすさを損なわない範囲内で、if文の条件として楽に記述できる文字数となる。

 実際に記述した例をリスト7.19に示す。

using System;
using System.Linq; // Anyメソッドを使うために必要

class Program
{
  static void Main(string[] args)
  {
    int[] a = { 1, 2, 0 };

    if (a.Any(x => x == 0))
    {
      Console.WriteLine("テストデータに0が含まれています。");
      return;
    }
    foreach (int n in a) Console.WriteLine(100 / n);
  }

  // 出力:テストデータに0が含まれています。
}
リスト7.19 ラムダ式を用いて計算開始前に0チェックを行う

 「Anyメソッド」は、コレクションの要素の中に1つでも引数のラムダ式を満たすものが含まれていればtrueになる。これは.NET Framework 3.5で拡張されたメソッドであり、使用するためにはコードの先頭に「using System.Linq;」が必要である。その名のとおり、LINQ用のライブラリで拡張されたメソッドであるが、これらには、複雑なクエリを行わない場合にも便利なメソッドが多い。

 もし、.NET Framework 3.5が使用できない場合は、リスト7.19のif文を次のように記述することで(やや冗長になるが).NET Framework 2.0でも同様のチェックを実現できる。

if (Array.FindIndex(a, x => x == 0) >= 0)

 この例は、データの固まり(コレクション)に対する処理の指示を短いラムダ式で記述することにより、1つの値に対するチェックである「if ( n == 0 )」と同じような感覚でコレクションに対するチェック「if (a.Any(x => x == 0))」を記述できることを示している。

 つまり、これまでコレクションに対するループとして記述されてきたコレクション要素の判定処理が、たった1つのif文に置換できることを示している。このようなテクニックを常用すると、明らかにソースコードの雰囲気が変わり、簡潔になる。

【C#olumn】「=>」は不等号?

 BASIC系の言語など、不等号を記述する際に「=」と「>」の順番が規定されていない言語がある。そのような言語では、「>=」と「=>」の意味は等価である。そのため、このような言語に親しんでいると「=>演算子」が不等号を記述しているように見えることがあるかもしれない。

 たとえば、次のようなラムダ式は実際にありうるし、これは上記のような言語の経験者にはまさに不等号そのもの見えるだろう。

x => 0

 ただし、Visual BasicのIDEを使うプログラマーであれば、不等号としての「=>」はめったに見ていないはずである。なぜかといえば、IDEで入力した際に、「=>」は即座に「>=」に置き換えられてしまうからである(Visual Basic 6.0とVisual Studio 2008で確認)。

 それらを考え合わせると、「=>」を不等号として扱うことのできるプログラミング言語でコードを書く場合でも、そのような表記は使わないように習慣付けたほうがよいだろう。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter7 ラムダ式(後編)
    1.7.1 ラムダ式は何をもたらすか?
    2.7.2 ラムダ式と匿名メソッドの違い
    3.7.3 ステートメント型のラムダ
    4.7.4 式形式のラムダの可能性
    5.7.5 型指定を省略できる場合、できない場合
    6.7.6 何もしないラムダ式
  7.7.7 ラムダ式の使用例/【C#olumn】「=>」は不等号?
    8.7.8 ラムダ式のさまざまなバリエーション
    9.7.9 ジェネリックメソッドと型推論
    10.7.10 オーバーロードの解決/値型と参照型の相違は何か?/練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間