List<>::Find() 등의 검색 메서드에서 조건을 지정할 때 사용하는 Predicate<> 타입의 대리자. MSDN에는 인수를 지정할 수 없는 static 함수형 예제만 나와 있는데, 이보다 더 많이 쓰이게 될 형식은 객체형 대리자 및 무명 메서드이다. 다음은 MSDN에 올라온 함수형 predicate 사용법의 예제다.
using System;
using System.Drawing;
public class Example
{
public static void Main()
{
Point[] points = {
new Point(100, 200),
new Point(150, 250),
new Point(250, 375),
new Point(275, 395), new Point(295, 450) };
Point first = Array.Find(points, ProductGT10);
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
}
private static bool ProductGT10(Point p)
{
return (p.X * p.Y > 100000);
}
}
C#
복사
위 예제 predicate의 비교 구문 중 100000이란 조건을 임의의 수치로 바꾸고자 할 경우, 함수형 Predicate으론 외부 객체를 사용하지 않고서는 해결할 방법이 없다. 바로 이 때가 무명 메서드와 객체형 대리자가 등장할 좋은 시점이다.
다음은 무명 메서드를 이용한 방법이다.
...
int cond = 50000;
Point first = Array.Find(points,
delegate(Point p) { return (p.X * p.Y > cond); }
...
C#
복사
해당 Predicate의 호출자 앞에 조건(int cond = 50000;)을 넣고 아예 Predicate으로 무명 메서드를 박는 방법으로서, 인수를 넘기는 방법을 제공함과 동시에 코딩 오버헤드를 크게 줄이고 있다.
다음은 객체형 Predicate을 이용한 방법이다(C#).
...
int cond = 50000;
Point first = Array.Find(points, (new IsBigger(cond)).Match);
...
...
class IsBigger
{
int cond;
public IsBigger(int cond) { this.cond = cond; }
public Predicate<Point> Match { get { return IsMatch; } }
bool IsMatch(Point p) { return (p.X * p.Y > this.cond); }
}
C#
복사
익명 메서드와 동일한 효과를 내지만 코딩 오버헤드가 크다는 것이 단점인데, 많이 쓰이게 될 경우에는 객체형 Predicate이 더 효율적이겠다. 하지만 C++/CLI에서는 익명 메서드를 지원하지 않으므로 객체형 Predicate 외에는 선택의 여지가 없다.
다음은 위 코드에 대한 C++/CLI 코드..
...
int cond = 50000;
Point first
= Array::Find(points, (gcnew IsBigger(cond))->Match);
...
...
ref class IsBigger
{
int cond_;
public:
IsBigger(int cond) { cond_ = cond; }
property Predicate<Point>^ Match
{
Predicate<Point>^ get()
{
return
gcnew Predicate<Point>(this, &IsBigger::IsMatch);
}
}
private:
bool IsMatch(Point p) { return (p.X * p.Y > cond_); }
};
C#
복사
C++/CLI에서는 함수에 대한 대리자 직접 변환을 지원 안하기 때문에 Predicate<>대리자를 직접 호출해야 한다는 점이 눈에 뜬다. C++/CLI의 특수성으로 인해 C#코드보다 지저분한 것이 사실이다.