LINQ 는 Language INtegrated Query위 약어로, 컬렉션을 편리하게 다루기 위한 목적으로 만들어진 질의 언어입니다. C# 3.0 버전에서부터 탑재한 LINQ 덕분에 프로그래머들은 데이타를 찾고 병합하고 정렬하는 코드를 작성하는 짐을 상당 부분 내려 놓을 수 있게 되었습니다.
예제3 - select 문의 분석
select 절은 다음과 같이 사용하면 됩니다.
var profiles = from profile in arrProfile
where profile.Height < 175
orderby profile.Height ascending
select profile;
위의 예에서 var 형식으로 선언된 profiles 의 실제 형식이 궁금할 겁니다. C# 컴파일러가 var 형식을 LINQ 쿼리식이 반환할 결과 형식에 맞춰 알아서 컴파일 해 주기는 하지만, 실제로 var 가 어떤 형식으로 치환되는지를 알아둘 필요가 있습니다. LINQ 질의 결과는 IEnumerable<T> 로 치환되는데, 이 형식 매개변수 T는 select 문에 의해 결정됩니다.
예를 들어 위 LINQ 쿼리식은 배열로부터 175 미만인 Profile 객체를 골라내는데, 그 결과는 IEnumerable<Profile> 형식이 됩니다. 다음과 같이 select 문에서 Profile 객체 전체가 아닌 Name 프로퍼티만 추출하면 profiles는 IEnumerable<string> 형식으로 컴파일됩니다.
var profiles = from profile in arrProfile
where profile.Height < 175
orderby profile.Height ascending
select profile.Name;
추가적으로 select 문은 무명 형식(Anonymous type)을 이용해서 다음과 같이 새로운 형식을 만들어 낼 수도 있습니다.
var profiles = from profile in arrProfile
where profile.Height < 175
orderby profile.Height ascending
select new { Name = profile.Name, InchHeight = profile.Height * 0.393 };
전체 소스
class Profile
{
public string Name { get; set; }
public int Height { get; set; }
}
class Program
{
static void Main(string[] args)
{
Profile[] arrProfile = {
new Profile{Name = "이순신", Height=210},
new Profile{Name = "강감찬", Height=169},
new Profile{Name = "을지문덕", Height=175},
new Profile{Name = "세종대왕", Height=183},
new Profile{Name = "안창호", Height=159},
new Profile{Name = "연개소문", Height=172}
};
// 1단계 - 키가 175 미만인 데이타를 추출함
var profiles = from profile in arrProfile
where profile.Height < 175
orderby profile.Height ascending
select new { Name = profile.Name, InchHeight = profile.Height * 0.393 };
// 2단계 - 출력함
foreach (var profile in profiles)
Console.WriteLine("{0}, {1}", profile.Name, profile.InchHeight);
Console.ReadLine();
}
}
예제4 - where 조건에 and, or 연산자 사용하기 / 여러개의 데이타 원본에 질의하기
LINQ 쿼리식은 데이타 원본에 접근하기 위해 from 절을 사용합니다. 여러개의 데이타 원본에 접근하려면 from 절을 중첩해서 사용하면 됩니다.
foreach 문을 중첩해서 사용하는 것처럼 말입니다.
다음의 클래스는 각 학년별, 학급별, 점수를 나타내며, 과목별 점수를 담기 위해 Score 필드를 배열로 선언했습니다.
class GradeClassScore
{
public int Grade { get; set; }
public string ClassName { get; set; }
public int[] Score { get; set; }
}
그리고 이 클래스를 바탕으로 배열 하나를 다음과 같이 선언했습니다.
GradeClassScore[] arrClass = {
new GradeClassScore(){Grade = 1, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
new GradeClassScore(){Grade = 1, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
new GradeClassScore(){Grade = 1, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
new GradeClassScore(){Grade = 1, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
new GradeClassScore(){Grade = 1, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
new GradeClassScore(){Grade = 2, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
new GradeClassScore(){Grade = 2, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
new GradeClassScore(){Grade = 2, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
new GradeClassScore(){Grade = 2, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
new GradeClassScore(){Grade = 2, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
new GradeClassScore(){Grade = 3, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
new GradeClassScore(){Grade = 3, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
new GradeClassScore(){Grade = 3, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
new GradeClassScore(){Grade = 3, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
new GradeClassScore(){Grade = 3, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}}
};
이제 준비는 마쳤습니다. 위 배열에서 1학년 중에서 점수가 60점 미만인 학급과 과목 점수를 중첩 from 절을 이용해서 뽑아 보겠습니다. 그리고 여기서 한가지 팁을 더 알려 드리자면 where 절에 and, or 를 포함 시킬 수 있습니다. 즉 and => &&, or => || 를 사용하시면 됩니다.
var classes = from c in arrClass
from s in c.Score
where s < 60 && c.Grade == 1
orderby s
select new { c.ClassName, Lowest = s };
전체 소스
class GradeClassScore
{
public int Grade { get; set; }
public string ClassName { get; set; }
public int[] Score { get; set; }
}
class Program
{
static void Main(string[] args)
{
GradeClassScore[] arrClass = {
new GradeClassScore(){Grade = 1, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
new GradeClassScore(){Grade = 1, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
new GradeClassScore(){Grade = 1, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
new GradeClassScore(){Grade = 1, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
new GradeClassScore(){Grade = 1, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
new GradeClassScore(){Grade = 2, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
new GradeClassScore(){Grade = 2, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
new GradeClassScore(){Grade = 2, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
new GradeClassScore(){Grade = 2, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
new GradeClassScore(){Grade = 2, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
new GradeClassScore(){Grade = 3, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
new GradeClassScore(){Grade = 3, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
new GradeClassScore(){Grade = 3, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
new GradeClassScore(){Grade = 3, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
new GradeClassScore(){Grade = 3, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}}
};
var classes = from c in arrClass
from s in c.Score
where s < 60 && c.Grade == 1
orderby s
select new { c.ClassName, Lowest = s };
foreach(var c in classes)
Console.WriteLine("낙제 : {0} ({1})", c.ClassName, c.Lowest);
Console.ReadLine();
}
}