PROGRAMMING WORKSHOP

Skip Navigation Links. Skip Navigation Links.

VB.Net |
LINQ & LAMBDA Expression| Start LINQ

이제 대강 Delegate,LAMBDA,Extesion Method등의 개념을 약간 챙겼으니까..
LINQ를 중심으로 위의 각각의 단어들과 비교하면서 예를 들어가면서
진행해보도록 하자

프로그래밍은 단일 정보 하나만 갖고 하는 것이 아니다
수많은 정보들이 떼거지로 옮겨 다닌다..
예를 들어서 회원관리를 한다고 치자
회원도 수백,수천이 될 것이고, 또 회원이라는 하나의 정보가 갖고 있는 것도
이름,성별,생년월일등등 아주 다양한 정보를 갖고 있을 것이다
이런 정보를 다루기 위하여 전통적 프로그래밍방법에서 순환문은 필수적이다
이것을 어떻게 순환문을 개발자가 사용하지 않으면서 간단하게 처리하는 방법은 없을까??
그래서 만들어진 것이 LINQ라는 언어이다
Language Integrated Query 의 약자이다
많은 정보를 순환하는 이유는 많은 정보중에서 나이가 30살이상인사람을 찾고
싶다거나, 수학점수가 90점이상인 학생을 걸러내가나 그런 조건에 맞는 것을
찾기 위한 것, 그렇게 질문을 던져서 찾아낸다는 단어가 Query 일 것이니까..
언어에 통합되어 있는 쿼리!!! 라고 하면 좋겠다
즉 VB언어자체에 Query기능을 갖게 하자..원하는 것을 순환문을 돌면서
찾지 않고 사용자가 그냥 VB언어에 표현을 하면 찾게 하는 것..

하나 간단한 것 부터 시작해보자..
그림과 같이 숫자로 이루어진 배열이 왼쪽 텍스트박스에 있다고 치자..



이것을 각각의 숫자를 짝수만 골라내고
또한 골라낸것의 합계를 내어라..!! 라는 문제가 있다면
VBA에 내공이 쌓이고, VB.Net의 일반적 코딩에 내공이 쌓였다면 이까것...문제도 아니다
그냥 순환문 돌리면서 골라 내면 된다
아래와 같이..

Dim sQ As String
Dim oQ As New List(Of Integer)
Dim iTotal As Integer = 0
For Each sQ In Me.TextBox1.Text.Split(",")
	Dim iX As Integer = CInt(sQ)
	If iX Mod 2 = 0 Then
		oQ.Add(iX)
		iTotal += iX
	End If
Next

텍스트박스의 내용을 콤마로 구분된 배열로 만들고
이 배열을 순환하면서 문자를 숫자로 변환하여
숫자가 짝수이면 집합체 oQ 에 추가하고, iTotal값을 계속 합계를 한다
이것이 해법일 것이다
그런데 이것을 LINQ로 풀면..

Dim sX As String() = Me.TextBox1.Text.Split(",")

Dim Q = From M In sX
	Where M Mod 2 = 0
	Select M

Label1.Text = "합계는 " & Q.Sum(Function(x) CInt(x))

뭐야..이게 전혀 외계인의 문법같다!!!
빨강색으로 표현한 것이 LINQ의 키워드들이다..
DB를 처리할때 SQL문을 기억하시면 된다..
SQL문과는 전혀 다른내용이지만 표현하는 형식이 비슷하다
그러니 SQL문에 능숙하였다면 거저 먹는 것으로 보시면 된다
말하듯이 하는 것이다
sX라는 집합체(여기에서는 배열)에서(IN) 각각의 요소(M)를(From) 순환하면서
그 요소값이 짝수이면(Where 조건절) 그것만 뽑아라(Select)
이렇게 말로 명령한 것이다
이 키워드에 능숙하게 되면 ..그냥 집합체만 보면 키워드를 디리대면 된다
어떤 조건에 맞는 값들 찾는 과정에서의 순환문 잊어도 된다..

위에서 찾아낸 결과는 또한 집합체이다..
이때 LINQ는 다양한 집합체를 다둘수 있다고 하였으니..
결과물이 어떤 정보타입의 집합체가 될지는 알수가 없다
그래서 VB.Net 즉 .Net FrameWork에서 제공하는 개체가
IEnumerable이라는 개체이다..이것은 다양한 타입의 정보의 집합체를
받아준다..
그래서 위에서
Dim Q = ......
이라고 한것을
Dim Q As String=....
라고 하면 에러가 난다..
그냥
Dim Q = .... 라고 하면 디폴트로 IEmumerable 개체타입인 것이다
그러니 그냥 Dim Q = .... 라고 하시고 결과물을 처리할때 집합체가 갖고 있는
타입에 따라서 처리하면 된다

그다음에 또 히안한 표현이 있다
LINQ의 결과로 나타난 집합체를..

Label1.Text = "합계는 " & Q.Sum(Function(x) CInt(x))

Label1의 Text속성에 결과물을 합계를 내서 문자열과 합쳐서 표현했다
여기에서 Q.Sum 이라고 하는 것은 Q라는 집합체즉 IEmumerage개체의
Extension Method 라고 한다..
VBA나 전통적인 이전의 VB에서는 배열등의 집합체를 처리할때는
순환을 하면서 계산을 하였지만..
IEnumerable이라는 집합체를 상속받는 다양한 집합체들은 모두 같은
편리한 다양한 메소드를 사용할수 있는 것이다

첫페이지에서 이야기했던 Extension Method 인것이다..
이때 Q.Sum(Function(x) CInt(x)) 라고 한것, 괄호안에 있는 것은..LAMBDA표현식이고
Q.Sum(AddressOf ....)를 사용하여 별도의 Delegate를 부를수도 있으나
간단한 것이니까..그냥 Inline delegate로 처리한것이다
그런데 위에서 보면 얻어온 값을 처리하는 것을 순환을 한다..
이것 마저 순환을 하지 않게 할수 없을까?

두번째 버튼에 아래와 같은 내용으로 작성해 보자

Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
Dim sX As String() = Me.TextBox1.Text.Split(",")

Dim Q As IEnumerable(Of String) = From M In sX
		Where M Mod 2 = 0
		Select M

Label1.Text = "합계는 " & Q.Sum(Function(x) CInt(x))
TextBox2.Text = ""
Q.ToList.ForEach(Sub(x)
		 TextBox2.Text &= x & ","
		 End Sub)

End Sub

값을 찾아 오는 것도 순환하지 않고
값을 뿌리는 것도 순환하지 않았다..
당초에 Q라는 불특정 집합체타입에 결과물을 받던 것을
IEnumerable(Of String)이라는 구체적인 타입으로 받아서
값을 뿌리는 것도 List개체의 ForEach라는 extension method에
inline Delegate를 lambda 표현식으로 작성한 것

IEnumerable타입에는 ForEach 라는 extension method가 없으니
ToList로 목록개체로 변환하면 사용할수 있는것..

참으로 헷갈릴 것이다, LINQ, Delegate, Extesion Method, Lambda expression
이것은 모두 LINQ라는 큰 제목하에 공존하는 것들이니..
자꾸하면서 익숙해 질 것이다
아무튼 목적은 말하듯이 주절거리면서 글을 쓰면
그것이 컴퓨터가 알아듣게 하기 위한 것..
좀더 인간친화적이고 속도도 빠르게 하려고 내부적으로 .Net FrameWork에서
노력하는 것일 것이다

정보처리를 하는데 있어서 그동안의 VB, VBA문법으로는
순환문을 작성하여야하는 것이 기본이였다
LINQ를 익숙하게 하게 되면 집합체정보만 보면 사용하게 되는
코딩이 될 것이다
물론 기존의 순환문작성으로 안되는 것은 하나도 없다
그러나 좀더 세련된 방식에 도전해보는 것이 좋지 않겠는가?

***[LOG-IN]***