using System;
using System.Linq;
/*
from 문 중첩:
여러 개의 데이터 원본에 질의(쿼리)하기
*/
// from 문을 중첩하면 여러 개의 데이터 원본에서 데이터를 쿼리할 수 있음을 보여줌
namespace FromFrom
{
class Class // Name과 Score 프로퍼티를 가집니다.
// Name은 문자열 타입이고, Score는 정수형 배열 타입입니다.
{
public string Name { get; set; }
public int[] Score { get; set; }
}
class MainApp
{
static void Main(string[] args)
{
Class[] arrClass =
{
new Class(){Name="연두반", Score=new int[]{99, 80, 70, 24}},
new Class(){Name="분홍반", Score=new int[]{60, 45, 87, 72}},
new Class(){Name="파랑반", Score=new int[]{92, 30, 85, 94}},
new Class(){Name="노랑반", Score=new int[]{90, 88, 0, 17}}
};
var classes = from c in arrClass // arrClass 객체에 from 절로 접근해서 범위 변수 c를 뽑고,
from s in c.Score // 다시 그 c 객체의 Score 필드에 또 다른 from 절로 접근해서
// 새로운 범위 변수 s를 뽑습니다.
// 범위 변수 s는 개별 점수를 나타냅니다.
where s < 60 // where 절을 사용해서 이 s가 60보다 낮은지 걸러내고,
orderby s
select new { c.Name, Lowest = s }; // new {...} 부분을 통해 무명 형식을 선언해서
// 낙제점을 맞은 학생의 학급 이름과 점수를 담아냅니다.
foreach (var c in classes) // classes 쿼리 결과를 순회하면서 각 익명 객체를 c 변수에 할당합니다.
Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})"); // c 변수를 통해 익명 객체의 Name과 Lowest 프로퍼티에 접근하여
// "낙제 : {반 이름} ({낙제 점수})" 형식으로 출력합니다.
}
}
}
/*
출력 결과
낙제 : 노랑반 (0)
낙제 : 노랑반 (17)
낙제 : 연두반 (24)
낙제 : 파랑반 (30)
낙제 : 분홍반 (45)
*/
코드 설명
이 C# 코드는 LINQ의 from 문을 중첩하여 사용하는 방법을 보여주는 예제입니다. from 문을 중첩하면 여러 개의 데이터 원본에서 데이터를 쿼리할 수 있습니다.
Class 클래스는 Name과 Score 프로퍼티를 가집니다. Name은 문자열 타입이고, Score는 정수형 배열 타입입니다.
MainApp 클래스의 Main 메서드에서는 4개의 Class 객체를 생성하여 arrClass 배열에 저장합니다. 각 Class 객체는 반 이름과 학생들의 점수를 나타냅니다.
from c in arrClass는 arrClass 배열의 각 요소를 c라는 변수에 할당하며 쿼리를 시작합니다.
from s in c.Score는 c 객체의 Score 배열의 각 요소를 s라는 변수에 할당하며 중첩된 쿼리를 시작합니다.
where s < 60는 s 값이 60보다 작은 경우, 즉 낙제 점수인 경우에만 요소를 선택합니다.
orderby s는 선택된 요소를 s 값을 기준으로 오름차순으로 정렬합니다.
select new { c.Name, Lowest = s }는 익명 형식을 사용하여 Name과 Lowest 프로퍼티를 가진 새로운 객체를 생성합니다. Name은 c 객체의 Name 프로퍼티 값이고, Lowest는 s 값입니다.
foreach (var c in classes)는 classes 쿼리 결과를 순회하며 각 요소를 c라는 변수에 할당합니다.
Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})");는 c의 Name과 Lowest 프로퍼티 값을 출력합니다.
출력 결과
낙제 : 노랑반 (0)
낙제 : 노랑반 (17)
낙제 : 연두반 (24)
낙제 : 파랑반 (30)
낙제 : 분홍반 (45)
select new { c.Name, Lowest = s };
foreach (var c in classes)
Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})");
이 부분은 LINQ 쿼리 결과를 익명 형식으로 만들어서 낙제생 정보를 출력하는 부분입니다.
select new { c.Name, Lowest = s }; 에서 select는 쿼리 결과로 어떤 데이터를 선택할지 지정하는 키워드입니다. 여기서는 new { c.Name, Lowest = s } 부분을 통해 익명 형식을 사용하고 있습니다.
익명 형식은 이름이 없는 클래스와 같습니다. 컴파일러가 자동으로 클래스를 만들어 주고, 그 안에 c.Name과 Lowest = s 두 개의 프로퍼티를 만들어서 낙제생 정보를 저장합니다.
c.Name은 현재 반의 이름을 나타내고, Lowest = s는 낙제 점수(s)를 Lowest라는 프로퍼티에 저장하는 것을 의미합니다.
foreach (var c in classes)는 classes 쿼리 결과를 순회하면서 각 익명 객체를 c 변수에 할당합니다.
Console.WriteLine($"낙제 : {c.Name} ({c.Lowest})");는 c 변수를 통해 익명 객체의 Name과 Lowest 프로퍼티에 접근하여 "낙제 : {반 이름} ({낙제 점수})" 형식으로 출력합니다.
이렇게 익명 형식을 사용하면 쿼리 결과를 간결하게 표현하고, 필요한 정보만 선택적으로 저장할 수 있습니다.