ラムダ(またはクロージャ)は、関数ポインターと変数の両方をカプセル化します。これが、C#で次のことができる理由です。
int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
return i < lessThan;
};
そこで、クロージャとして匿名デリゲートを使用しました(構文はラムダの同等のものよりも少し明確でCに近いです)。これにより、lessThan(スタック変数)がクロージャに取り込まれました。クロージャが評価されると、lessThan(スタックフレームが破棄された可能性があります)が引き続き参照されます。lessThanを変更すると、比較が変更されます。
int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
return i < lessThan;
};
lessThanTest(99);
lessThan = 10;
lessThanTest(99);
Cでは、これは違法です。
BOOL (*lessThanTest)(int);
int lessThan = 100;
lessThanTest = &LessThan;
BOOL LessThan(int i) {
return i < lessThan;
}
ただし、2つの引数を取る関数ポインタを定義できます。
int lessThan = 100;
BOOL (*lessThanTest)(int, int);
lessThanTest = &LessThan;
lessThanTest(99, lessThan);
lessThan = 10;
lessThanTest(100, lessThan);
BOOL LessThan(int i, int lessThan) {
return i < lessThan;
}
しかし、今、私はそれを評価するときに2つの引数を渡さなければなりません。この関数ポインターをlessThanがスコープ内にない別の関数に渡したい場合は、チェーン内の各関数に渡すか、グローバルにプロモートすることで、手動で関数ポインターを存続させる必要があります。
クロージャをサポートするほとんどの主流言語は無名関数を使用しますが、その必要はありません。匿名関数なしのクロージャと、クロージャなしの匿名関数を使用できます。
概要:クロージャは、関数ポインターとキャプチャーされた変数の組み合わせです。