람다 (또는 클로저 )는 함수 포인터와 변수를 모두 캡슐화합니다. 이것이 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이 범위에 포함되지 않은 다른 함수로 전달하려면 체인의 각 함수에 전달하거나 전역으로 승격하여 수동으로 유지해야합니다.
클로저를 지원하는 대부분의 주류 언어는 익명 함수를 사용하지만 이에 대한 요구 사항은 없습니다. 익명 함수없이 클로저를 가질 수 있고 클로저없이 익명 함수를 가질 수 있습니다.
요약 : 클로저는 함수 포인터 + 캡처 된 변수의 조합입니다.