PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net |

Predecate Delegate

Func , Action Delegate와 더불어 대표적인 System에서 제공되는 유용한
Delegate는 Predicate 라고 하는 것..
어휴..뭐 이런 별로 쓸모없어 보이는(처음에는 그렇게 보인다)것이 끝나고
Window Form의 콘트롤이나, DB나 엑셀을 VB.Net으로 만드는 Addin인 VSTO를
하려나...하시겠지만, 언제 해도 하여야 할 것들이다
그래야 .NetFrameWork의 자원을 적극적으로 활용할수 있다
좀더 흥미로움에 가까워져가는 것이 Predicate Delegate
Action Delegate는 Return값이 없고
Func Delegate는 Return값이 있고
Predicate Delegate는 Return값이 있고...
어라 그럼 Func와 Predicate는 뭐가 다른거야??
Predicate Delegate는 특별한 Func Delegate이다
Func Delegate와 같은데 이것은 논리값(Boolean)만 처리한다
Predicate가 먼저 만들어지고,
나중에 Func가 만들어졌다..
우리도 프로그래밍하면서 함수를 만들어 사용하다 보면 A라는 것을 만들어쓰고
나중에 B를 만들어 쓰고, 몇개를 만들어 쓰다 보면
비슷한 기능의 것이 몇개가 만들어져있는 것을 본다
.NerFrameWork에서도 당초에 논리값을 단순히 비교하는 Predicate를 만들어 쓰다가
앞으로 이야기 할 LINQ라는 것이 생기면서,
다른값도 처리하고, 많은 매개변수도 처리하는
Func Delegate를 만들게 되다 보니, 기능이 중복된 것이지만
Predicate Delegate만들 받아주는 메소드들이 있으니 알아야 한다



예를 들어서..
엑셀의 행에서 조건에 맞는 것을 찾고 싶다면

Dim oCol As New Collection
Dim rRow As Range
For Each rRow In rTable.Rows
   If rRow.Cells(1)="A" Then
      oCol.Add rRow
   End If
Next

에서 빨강색은 논리값을 표현하는 식이다, True인가 False 인가에 따라서
작업을 하게 되는 것이다
프로그래밍은 논리값에 따라서 모든 것이 결정된다



그림과 같이 VBA의 Collection개체에는 메소드가 몇개 없다
이렇게 모아놓은 집합체에서 어떤 조건에 맞는 정보를 찾아 내려면
또 이 집합체를 순환해야 한다
이것 보다는 Collection집합체에 다양한 일을 하는 메소드를 좀더 만들어져있다고 한다면
편리할텐데.. !!?? 하는 답이 바로 VB.Net에 있는 것이다
바로 이부분에서 VB.Net에서는 이 개체에 다양한 메소드가 붙어 있고
이 메소드가 매개변수로 Delegate를 받아들이게 만들어진 것이다
그래서 Delegate의 개념을 알고 있어야 다양한 집합체에 일을 간단하게 시킬수 있는 것이다
아하..메소드에 함수나 프로시져를 매개변수로 전달한다는 개념이로구나!!!
라고 감을 잡으신다면, 몇페이지에 걸쳐서 알듯말듯한 소리를
한것에 대하여 보람을 느끼는 셈이다
아래에서 List(Of String)개체에 값을 몇개 넣고
List(Of String)은 VBA의 Collection개체의 진화된 집합체로 우선 보시면 된다
List(Of Integer)
List(Of 어떤 데이타타입이던...)
와 같이 집합체는 집합체인데 어떤 타입의 정보를 모을 것인지
지정을 하고 모아주는 집합체이다
무지 편리한 것이다, 배열과 Collection개체의 통합이라고 할수도 있고
물론 이집합체 말고도 다양한 집합체가 있지만
List(Of T) 개체는 대표적이라고 할만하다
아무튼 이개체에 몇개의 정보를 아래와 같이 담고
이 모아진 정보에서 a라는 문자가 들어있는 아이템을 찾고 싶다면
VBA의 Collection 개체나 배열에서는 어쩔수 없이 순환을 하면서
찾아내야 한다

Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
	sCriteria = "a"
	Dim myPredicate As New Predicate(Of String)(AddressOf myFunc)
	Dim list As New List(Of String)
	list.Add("Apple")
	list.Add("Banana")
	list.Add("Orange")
	list.Add("Melon")
	list.Add("Grape")
	Dim foundString As String = list.Find(myPredicate)
	MsgBox(foundString)
End Sub
Function myFunc(sX As String)
	Return sX.Contains(sCriteria)
End Function

하지만 위의 프로시져에서는
list.Find 라는 메소드를 사용하고
Find 메소드는 Predicate Delegate를 매개변수로 요구한다!!
아하..그래서 Delegate가 필요한 것이구나..
이런 식으로 .NetFrameWork의 크래스들을 적극적으로 활용하려면
이런 기본을 알아야 하는 것이다

아래의 그림과 같이 어떤 메소드는 Action Delegate를 요구하고
또 다른 메소드는 Predicate Delegate를 요구하고



아주 많은 메소드가 제공되는데 매개변수로 요구하는 Delegate를 이해하고
있지 않으면 말짱 쓸모없는 메소드가 되는 셈이다
그러니 이해하려고 꾸준히 페이지를 차근 차근 보셨다면
보람을 느끼시게 될 것이다

위에서 별도의 프로시져를 참조(Referncing)하지 않고
Lambda expression으로 표현한다면 아래와 같겠다
이것을 anonymous funciton으로 delegate를 실행하는 것이라고 말할수 있겠다

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim lookFor As String = "e"
        Dim myPredicate = Function(s As String) s.Contains(lookFor)

        Dim list As New List(Of String)
        list.Add("Apple")
        list.Add("Banana")
        list.Add("Orange")
        list.Add("Melon")
        list.Add("Grape")
        Dim foundString As String = list.Find( myPredicate )
        MsgBox(foundString)
End Sub

위에서 List(of String)집합체에서 Find를 하였을때는 처음 조건에 맞는 것을 하나만
갖여 온다
하지만 조건에 맞는 것을 모두 가져 오려면 FindAll 메소드를 사용하게 된다
하나만 가져 올때는
Dim foundString As String=list.Find(...)
로 문자열 변수에 하나만 받아온다..
하지만 FindAll을 하면 여러개의 문자열을 얻어오게 되니

Dim foundString As List(Of String) = list.FindAll(...)

라고 집합체로 받아야겠지..



***[LOG-IN]***