안녕하세요. 이번 글에서는 C#의 LINQ(Language Integrated Query) 기본 사용법에 대해 알아보겠습니다.
컬렉션에서 조건에 맞는 항목을 고르거나 정렬하고, 다른 형태로 바꾸는 작업을 for문과 if문으로 일일이 작성하면 코드가 길어집니다. LINQ는 이런 작업을 메서드 체인으로 간결하게 표현하는 기능입니다.
기본 사용법 : Where, Select, OrderBy
네임스페이스는 System.Linq이며, List, 배열 등 IEnumerable<T>를 구현한 모든 컬렉션에서 사용할 수 있습니다.
using System;
using System.Collections.Generic;
using System.Linq;
var numbers = new List<int> { 5, 2, 8, 1, 9, 4 };
// before
var result1 = new List<int>();
foreach (var n in numbers)
{
if (n > 3) result1.Add(n * 10);
}
result1.Sort();
// after
var result2 = numbers
.Where(n => n > 3) // 조건에 맞는 항목만
.Select(n => n * 10) // 다른 값으로 변환
.OrderBy(n => n) // 오름차순 정렬
.ToList();
Console.WriteLine(string.Join(", ", result2)); // 40, 50, 80, 90
자주 쓰는 메서드
| 메서드 | 설명 |
|---|---|
| Where | 조건에 맞는 항목 필터링 |
| Select | 각 항목을 다른 값으로 변환 |
| OrderBy / OrderByDescending / ThenBy | 정렬 / 내림차순 / 보조 정렬 |
| First / FirstOrDefault | 첫 항목 (없으면 예외 / 기본값) |
| Any / All | 하나라도 / 모두 조건에 맞는지 |
| Count / Sum / Min / Max / Average | 집계 |
| GroupBy | 키로 묶기 |
| Distinct | 중복 제거 |
| Take / Skip | 앞에서 n개 가져오기 / 건너뛰기 |
| ToList / ToArray | 결과를 컬렉션으로 확정 |
객체 컬렉션에서 활용
record Person(string Name, int Age, string Dept);
var people = new List<Person>
{
new("Kim", 30, "Dev"),
new("Lee", 25, "Dev"),
new("Park", 41, "HR"),
new("Choi", 35, "HR"),
};
// 30세 이상 이름만, 나이 내림차순
var names = people
.Where(p => p.Age >= 30)
.OrderByDescending(p => p.Age)
.Select(p => p.Name);
Console.WriteLine(string.Join(", ", names)); // Park, Choi, Kim
// 부서별 평균 나이
foreach (var g in people.GroupBy(p => p.Dept))
Console.WriteLine($"{g.Key} : {g.Average(p => p.Age)}");
// 조건 확인
bool hasSenior = people.Any(p => p.Age >= 40); // true
var first = people.FirstOrDefault(p => p.Dept == "QA"); // null
지연 실행 주의
Where, Select 같은 메서드는 호출 즉시 실행되지 않고, 결과를 실제로 순회할 때 실행됩니다. 이를 지연 실행(deferred execution)이라고 합니다. ToList, ToArray, Count 등을 호출하면 그 시점에 확정됩니다.
var list = new List<int> { 1, 2, 3 };
var query = list.Where(n => n > 1); // 아직 실행 전
list.Add(10); // 원본 변경
Console.WriteLine(string.Join(", ", query)); // 2, 3, 10 (순회 시점에 평가)
var snapshot = list.Where(n => n > 1).ToList(); // 이 시점에 확정
- 같은 쿼리를 여러 번 순회하면 매번 다시 실행되므로, 결과를 재사용한다면 ToList()로 확정합니다.
- First는 결과가 없으면 InvalidOperationException이 발생하므로, 없을 수 있다면 FirstOrDefault를 사용합니다.
- 순회 중 원본 컬렉션을 수정하면 예외가 발생할 수 있습니다.
정리
LINQ는 Where, Select, OrderBy 같은 메서드를 연결해 컬렉션의 필터링·변환·정렬·집계를 간결하게 표현합니다. 대부분의 메서드가 지연 실행되므로 결과를 여러 번 쓸 때는 ToList로 확정하고, 결과가 없을 수 있는 경우에는 FirstOrDefault를 쓰는 점만 주의하면 됩니다.
이상으로 LINQ 기본 사용법에 대해 간단히 알아보았습니다.