PROGRAMMING WORKSHOP

Skip Navigation Links. Skip Navigation Links.

VB.Net |
LINQ & LAMBDA Expression| delegate, func

LAMBDA 표현식의 각각의 키워드들은 이름 붙여지지 않은 내장함수라고
생각하시면 좋을 것이다
정통적인 방법으로 어떤 일을 시킬때는 함수(메소드)를 호출하여 일을 시키는 형식이지만
그냥 서술식으로 써나가지만 정해진 키워드들에 의하여 내부적으로 함수가
호출되어 정해진 일을 수행하게 만든 것이다
어떻게 하면 좀더 편하게 개발자들이 코딩을 하게 할수 없을까??
라는 생각에서 만들어진 새로운 코딩이라고 보셔도 좋을 것이다

매개변수를 어떤 타입으로 전달하고, 결과값을 어떤값으로 받아라!!라는
Rambda표현식을 작성할때 Func()라는 키워드가 나타난다..
이것이 무엇일까?
이것은 .NetFramework에 이미 만들어져서 제공되는 Delegate들이다
만들어서 사용할수도 있지만 제공되는 것을 필요에 따라서 사용하면 되는 것이다



와..뭐가 이렇게 많지, 그런데 뭣에 쓰는 것이지..
위의 것을 알기 전에 Delegate라는 중요한 키워드를 하나 챙기자
Delegate는 무언가 대신하는 대리인, 대표,무언가를 위임받은 사람등을 의미하듯이
무언가 대신한다..
아래와 같이 하고 실행을 해보시면..아하..하실 것이다


Delegate Function firstDelegate(ByVal sX As String) As String

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

	Dim oX As firstDelegate
	Randomize()

	If Int(Rnd() * 2) = 0 Then
		oX = AddressOf myFirstFunction
	Else
		oX = AddressOf mySecondFunction
	End If

	MsgBox(oX("ABCDEFGHIJK"))
End Sub
Function myFirstFunction(ByVal sX As String) As String
	Dim oX As New List(Of String)
	For iX As Integer = 0 To sX.Length - 1
		oX.Add(sX.Substring(iX, 1))
	Next
	oX.Reverse()
	Return Join(oX.ToArray, ",")
End Function
Function mySecondFunction(ByVal sX As String) As String
	Dim oX As New List(Of String)
	For iX As Integer = 0 To sX.Length - 1
		oX.Add(sX.Substring(iX, 1) & "000")
	Next
	oX.Reverse()
	Return Join(oX.ToArray, ",")
End Function

AddressOf 는 버튼등을 생성하고 크릭하면 어떤 프로시져를 실행하라고 할때
AddHandler myButton.Click, AddressOf [some procedure]
를 할때 사용하였던 기억이 나신다면 바로 이벤트프로시져가 Delegate라는 것을
사용하고 있다는 것을 아시면 된다
아래와 같이 프로시져(메소드)의 이름만 있고 내용은 없는 것과 같다.

Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click

End Sub

그러니 우리가 이미 사용하고 있는 것이였고..
Evnet Delegate 혹은 EventHadler Delegate라고 부를수 있을 것이다

이것은 매개변수를 두개를 갖는데 첫째 sender는 이벤트를 일으킨개체이고
두번째매개변수는 e As System.EventArg는 이벤트발생에 따른 부가정보를
갖고 있는것이다, 이것은 빈값일때도 있고, 어떤 중요한 정보를 전달하기도 하고..

여기에서 Delegate를 사용자정의로 만들어서 사용해 본 것이다
변수를 정의하여 값을 넣는 것과 같이
변수를 정의하여 함수이나 프로시져를 연결하는 것으로 보시면 좋을 것이다
그런데 위와 같이 사용자가 Delegate를 정의하여 사용하는 것도 필요하지만
VB.Net에서는 위와 같이 Delegate 템프릿을 만들어 놓고 사용하라고 해놓은 것이
위의 그림속의 Func, Func, Func 인것이다

Func( of T, T1,T2,,,TResult) 라고하는 것은
함수가 받는 매개변수는 of T(Type) 즉 어떤 타입의 값이고
함수의 결과값은 Tresult 즉 어떤 타입의 결과값이냐는 것을 지정하여
사용하라는 것이다
위의 내장되어 제공되는 Delegate 을 사용하여 보면..

Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
	Dim callFunc As Func(Of String, String, String) = AddressOf InsertCharX
	Dim sMyString As String = "VB.Net Is Great"
	MsgBox(callFunc(sMyString, "X"))
End Sub
Private Function InsertCharX(ByVal sX As String, ByVal sChar As String) As String
	Dim sTemp As String = ""
	For iX As Integer = 0 To sX.Length - 1
		sTemp &= sX.Substring(iX, 1) & sChar
	Next
	Return sTemp
End Function

Func(of T, T, Tresult)
즉 결과값이 String타입의 함수를 매개변수를 두개 전달하는
Delegate 템프릿 Func을 사용한 것이다

필요에 따라 매개변수가 많이 필요하면 많이 제공하는 템프릿을 사용하면 된다
다시 말하면 이것을 사용하면
Delegate function(sX As String,sY As String) As String
과 같이 Delegate를 선언할 필요없이 사용할수 있다는 편리함의 제공인 것이다
사용하기 싫으면 사용자정의로 선언하고 사용하도 되고,, 사용자마음대로..
그렇다면 함수가 아니고 섭프로시져는 없나??
있다..이것은 Func가 아니고 Action이라고 하는 아래의 그림과 같은 템프릿이다



아하, 이것은 결과값은 없구나..당연 , 섭프로시져니까.. 그림의 아이콘모양을 보면..아하 요렇게 생긴것이 Delegate 구나..
조금 더 해보자..
LAMBDA 표현식을 사용하여 함수를 별도로 하지 말고
Inline으로 표현해 보면 좋을 것이다

Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
	Dim oDummy As Func(Of String, String) = Function(s)
					Dim sX As String = ""
					For iX As Integer = 0 To s.Length - 1
						sX &= s.Substring(iX, 1) & "000"
					Next
					Return sX
					End Function

	MsgBox(oDummy("ABCDEFGHIJK"))
End Sub

그것참 흥미롭지 않은가..
그냥 한줄로 간단하게 표현할수도 있으니까..
oDummy라는 변수를 표현하는 식을 모두 Lambda표현식이라고 하는 것이다
간단한 것은 End Function같은 것없이 표현하여도 좋지만 많은 계산을 하는 것은
여러줄로 하여 End Function까지 사용하는 것도 좋을 것이지만
대개의 경우는 한줄로 줄 연결표현을 하면서 사용한다

그런데 도대체 왜 이런 것이 필요한지 모르겠다고 하실수 있다
이런 것을 조금씩 이해하게 되면 아래와 같이
여러개의 다양한 컨트롤을 그려 놓았다고 치자
Click하면 어떤 일을 하게 하고 싶다..일일이 각각의 개체의 Click 이벤트를
선택하여 코딩을 하는 것이 정석이라고 할수 있을 것이다
그러나..위에서 주절주절 이야기하는 것을 자꾸 이해하려고 노력하면
이렇게 이벤트프로시져를 하나로 작성하여 간단하게 할수 있는 센스가 생기게 된다



다양한 개체를 크릭할때 아래와 같이 하나의 프로시져를 만들고
기본적으로 다양한 이벤트에서 sender As Object와 e As EventArgs 라는 두개의
매개변수를 넣어주고, 뒤에 Handles 이라는 키워드를 사용하여
각 콘트롤의 발생이벤트를 줄줄이 적어 주면 하나의 프로시져에서
모두 소화시킨다

Sub ActionForAllControlClick(sender As Object, e As EventArgs) Handles Button8.Click, _
				Button7.Click, _
				Label1.Click, _
				ListBox1.Click, _
				NumericUpDown1.Click, _
				DateTimePicker1.Enter, _
				PictureBox1.DoubleClick, RadioButton1.CheckedChanged
	MsgBox("지금 " & sender.GetType.Name & " 개체를 크릭하였습니다")
End Sub

그런데 예를 들어서 DateTimePicker같은 것은 Click이벤트가 없다
이럴때는 비슷한 효과를 내는 Enter이벤트를 Handle(처리)하게 해주고
RadioButton같은 것도 Click이벤트가 없다 , 이것은 CheckedChanged이벤트를
처리하게 해주고..
그래서 매개변수 Sender As Object라고 특정한 개체가 아닌 범용의 개체타입으로
매개변수를 받게 한 것이다..
그리고 이것을
Sender.GetType 하면 해당타입이 무엇인지 알아내여 특정개체로 접근하고
이것에 Name속성을 붙이면 해당 컨트롤의 이름을 알게 되는 것이고..

Select Case CType(sender.GetType.Name)
Case "Button"
.....
Case "PictureBox"
.....
End Select

와 같이 하나의 프로시져에 모두 처리가 되는 셈이다..
이것이 Delegate를 활용하려고 하는 이유가 되고
이런 개념들이 앞으로 다룰 LINQ라는 파워풀한 언어등의
기본 베이스가 되는 셈이다

***[LOG-IN]***