2012/07/26

ラムダ式の自分なりの解釈2

前回に引き続きラムダ式の自分なりの解釈(自分用)です。

前回は匿名メソッドを「デリゲートを使用する際に外部に書き出してたメソッドをインラインで書けるようにしちゃおうというもの」という大雑把な解釈(?)で片付けて終わらせちゃいました。今回はそれを踏まえてラムダ式の解釈を行います。

早速、前回のサンプルをラムダ式で表してみましょう。ラムダ式の基本的な文法は「(入力パラメータ) => {式やステートメント}」となります。

static void Main(string[] args)
{
var message1 = "20の倍数です(スコープ外も参照できます)";

var thread1 = new Thread
(() =>
{
for (int i = 1; i < 100; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(250);

if (i % 20 == 0)
{
Console.WriteLine(message1);
}
}
});

var thread2 = new Thread
(() =>
{
for (int i = 100; i >= 1; i--)
{
Console.WriteLine(i.ToString());
Thread.Sleep(500);

if (i % 20 == 0)
{
Console.WriteLine(message1);
}
}
});

thread1.Start();
thread2.Start();
}
}

…我ながらなんていまいちなサンプルなんだ。どこが変わったか分かんないじゃないか。パラメータもないし(パラメータが無い場合は先頭が「()」空の括弧となります。)。

このままではあんまりなのでLINQを使ったサンプルをひとつ考えます。まずは前準備として以下のようなコードがあるとします。

class Employee
{
public string Cd { get; set; }
public string Name { get; set; }
}

class Program
{
static void Main(string[] args)
{
var employeeList = new List
{
new Employee{ Cd = "001", Name = "Tanaka" },
new Employee{ Cd = "002", Name = "Sato" },
new Employee{ Cd = "003", Name = "suzuki" },
new Employee{ Cd = "004", Name = "Tanaka" }
};

//タナカさんを探せ!!
foreach (var employee in employeeList)
{
if (employee.Name == "Tanaka")
{
Console.WriteLine(string.Format(
"Cd:{0},Name:{1}",
employee.Cd,
employee.Name));
}
}

Console.ReadLine();
}
}

なんだか毎度気合いの抜けたサンプルですが、Employeeデータを作成し、そこからタナカさんを探してコンソールに出力しています。これをLINQとラムダ式を使って変更すると以下のようになります。

class Employee
{
public string Cd { get; set; }
public string Name { get; set; }
}

class Program
{
static void Main(string[] args)
{
var employeeList = new List
{
new Employee{ Cd = "001", Name = "Tanaka" },
new Employee{ Cd = "002", Name = "Sato" },
new Employee{ Cd = "003", Name = "suzuki" },
new Employee{ Cd = "004", Name = "Tanaka" }
};

//タナカさんを探せ!!
foreach (var employee in employeeList.FindAll(n => n.Name == "Tanaka"))
{
Console.WriteLine(string.Format(
"Cd:{0},Name:{1}"),
employee.Cd,
employee.Name);
}

Console.ReadLine();
}
}

コードの量があんまり変わっていませんが、FindAllメソッドにラムダ式「n => n.Name == “Tanaka”」を割り当てています。FindAllメソッドに渡されるパラメータに「n」を指定していますが、別に「m」でも「c」でも「nn」でも「nnn」でも何でもよいです。最初は何だよ「n」だとか「p」だとかってと思ってましたがラムダ式の慣例だと思ってしまえば使っていく内に慣れると思います(下手な名付けするより使いやすいです)。ラムダ式を利用した結果、foreachの前にタナカさんが絞り込まれ、ループ回数が少なくなります。

このようにLINQ内で使う場合はラムダ式自体目的が明確になるので分かりやすいです。問題は以前の記事に出てくるようなメソッドのパラメータにラムダ式を入れなきゃいけないパターンです。まぁ、インテリセンスのパラメータのヒントにFuncデリゲートだとかActionデリゲートとかって出たらラムダ式かなって思うことにしようかと(自分的に)。

今更ながら全然解釈してない気もするけどまぁいいや。


pagetop