|
|
連載:[完全版]究極のC#プログラミング
Chapter6 ラムダ式(前編)
川俣 晶
2009/10/19 |
|
|
6.7 デリゲートインスタンスの等価性
デリゲートのインスタンスは、それ自体が一種の値なので、==演算子やEqualsメソッドなどで容易に同じであるかを調べられる。その際、ラムダ式には興味深い特徴が見られるので解説しておこう。
まず、別個のコードで生成されたデリゲートは、シグネチャや内容が同じでもイコールとは見なされないことを確認しよう(リスト6.10参照)。
using System;
class Program
{
static void Main(string[] args)
{
Action<int> m1 = (dummy) => { };
Action<int> m2 = (dummy) => { };
Console.WriteLine(m1 == m2); //出力:False
}
}
|
|
リスト6.10 別個のコードで生成されたデリゲートの比較 |
では、1つのデリゲート生成コードから生成されたデリゲートのインスタンスはイコールと見なされるのだろうか?(リスト6.11参照)
using System;
class Program
{
static void Main(string[] args)
{
Action<int>[] methods = new Action<int>[2];
for (int i = 0; i < 2; i++)
{
methods[i] = (dummy) => { };
}
Console.WriteLine(methods[0] == methods[1]); // 出力:True
}
}
|
|
リスト6.11 1つのデリゲート生成コードで2つのデリゲートを作る |
このようにイコールと見なされた。
だが、ここで安心してはいけない。なぜなら、同じコードから生成されたデリゲートがイコールと見なされないことがあるからだ(リスト6.12参照)。
using System;
class Program
{
static void Main(string[] args)
{
Action<int>[] methods = new Action<int>[2];
for (int i = 0; i < 2; i++)
{
int j = i;
methods[i] = (dummy) => { j++; };
}
Console.WriteLine(methods[0] == methods[1]); // 出力:False
}
}
|
|
リスト6.12 イコールと見なされないデリゲートの例 |
ここで追加したのは、変数jである。変数jはループを1回繰り返すごとに新しく誕生する。そして、ラムダ式は変数jを使用しているので、この変数jはキャプチャされる。実は、キャプチャされている変数が同じでなければ、デリゲートはイコールと見なされないのである。このケースでは、methods[0]がキャプチャしている変数jとmethods[1]がキャプチャしている変数jは別物なので、イコールとは見なされないのである。
逆に、「j++;」を「i++;」に書き換えると、結果はTrueに変わり、イコールと見なされる。この場合、2つのラムダ式がキャプチャしている変数iは同じものであるからだ。
このような仕様は、イコールの判定が、デリゲートを呼び出して同じ結果を出すか否かの判定に使用できることを意味する。キャプチャした変数が別物であれば、もちろん呼び出して同じ結果になるかどうかはわからない。しかし、同じ変数をキャプチャしていれば、同じ結果になると予測できるわけである。
Insider.NET 記事ランキング
本日
月間