| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- System Programming
- Data Structure
- 독서
- Unity
- PS
- multi-thread
- c#
- C++
- git
- Network Programming
- Online Judge
- Toy Project
- BOJ
- Today
- Total
I'm FanJae.
[20260519] C# 정리 ( LINQ ) 본문
1. 정의
- LINQ(Language Integrated Query)는 컬렉션 데이터를 손쉽게 검색, 필터링, 정렬, 변환, 집계할 수 있는 기능이다.
- 예를 들어, List 배열, Dictionary 같은 데이터에서 원하는 조건의 값만 찾거나 정렬하거나 필요한 값만 뽑아낼 때 사용한다.
- SQL을 사용해 본 사람이라면, LINQ의 문법이 낯이 익은데, LINQ의 의도 자체가 C# 코드 안에서 SQL 처럼 데이터를 질의할 수 있게 하는 것에 가깝다.
2. LINQ를 사용하는 이유
- 반복문으로 직접 조건을 검사하면 코드가 길어진다.
int[] numbers = {1, 2, 3, 4, 5, 6};
foreach(int number in numbers)
{
if (numbers % 2 == 0)
{
Console.WriteLine(number);
}
}
- 이때, LINQ를 사용하면 코드를 짧게 작성할 수 있다.
int[] numbers = { 1, 2, 3, 4, 5, 6 };
var evenNumbers = numbers.Where(number => number % 2 == 0);
foreach (int number in evenNumbers)
{
Console.WriteLine(number);
}
3. LINQ의 주요 기능
class Item
{
public string Name { get; private set; }
public string Type { get; private set; }
public int Price { get; private set; }
public int AttackPower { get; private set; }
public Item(string name, string type, int price, int attackPower)
{
Name = name;
Type = type;
Price = price;
AttackPower = attackPower;
}
public void PrintInfo()
{
Console.WriteLine($"{Name} / 타입 : {Type} / 가격 : {Price} gold / 공격력 : {AttackPower}");
}
}
List<Item> inven = new List<Item>();
inven.Add(new Item("체력 포션", "Potion", 300, 0));
inven.Add(new Item("마나 포션", "Potion", 500, 0));
inven.Add(new Item("나무 검", "Weapon", 700, 5));
inven.Add(new Item("철검", "Weapon", 700, 5));
inven.Add(new Item("전설의 검", "Weapon", 5000, 50));
(1) Where 조건 필터링
- Where는 조건에 맞는 데이터만 골라낸다.
- Where 같은 LINQ 메서드는 IEnumerable<T> 를 대상으로 데이터를 순회, 필터링, 변환하는 표준 쿼리 연산자다.
- ※ IEnumerable<T> 라고 적었지만, 순회할 수 있는 컬렉션 모든 것을 의미한다. (예시. array,List<T>, Stack<T>, Queue<T>, Dictionary 등등..)
List<Item> weapons = inven.Where(item => item.Type == "Weapon").ToList();
// 없는 버전
List<Item> weapons = new List<Item>();
foreach (Item item in inven)
{
if (item.Type == "Weapon")
{
weapons.Add(item);
}
}
(2) OrderBy / OrderByDescending - 오름차순 / 내림차순 정렬
- OrderBy는 오름차순 정렬이다.
- OrderByDescending은 내림차순 정렬을 의미한다.
List<Item> sortedPrice = inven
.OrderBy(item => item.Price)
.ToList();
// 없는 버전
List<Item> sortedPrice = new List<Item>(inven);
sortedPrice.Sort(ComparePrice);
static int ComparePrice(Item a, Item b)
{
return a.Price.CompareTo(b.Price);
}
(3) Select - 데이터 변환
- Select는 컬렉션의 각 데이터를 원하는 형태로 변환할 때 사용한다.
- 단순히 특정 값만 뽑아낼 수도 있고, 뽑아낸 값을 조합해서 새로운 형태를 만들 수도 있다.
int[] numbers = { 1, 2, 3, 4, 5, 6 };
var result = numbers.Select(number => number * 10); // 숫자를 뽑아서 10씩 곱한다.
(4) FirstOrDefault - 첫 번째 데이터 찾기
- FirstOrDefault는 조건에 맞는 첫 번째 데이터를 찾는다.
int[] numbers = {10, 20, 30, 40};
int firstValue = numbers.FirstOrDefault(number => number >= 25);
- 조건에 맞는 값이 없으면 기본값을 반환한다.
(5) Any - 조건 만족 여부 검사
- Any는 조건을 만족하는 데이터가 하나라도 있는지 검사한다.
bool hasExpensiveItem = inven.Any(item => item.Price >= 1000);
// 가격이 1000 이상인 아이템이 하나라도 있는지 확인
(6) Count - 개수 세기
- Count는 조건을 만족하는 데이터의 개수를 센다.
int weaponCount = inven.Count(item => item.Type == "Weapon");
Console.WriteLine(weaponCount); // Weapon 타입 아이템 개수 출력
4. 메서드 체이닝
- LINQ는 여러 메서드를 이어서 사용할 수 있다.
- 이를 메서드 체이닝(Method Chaining)이라고 한다.
var result = inven
.Where(item => item.Type == "Weapon")
.OrderBy(item => item.Price)
.Select(item => item.Name);
- 위 코드는 아래 순서대로 동작한다.
1. Type이 Weapon인 아이템만 고른다.
2. Price 기준으로 정렬한다.
3. 아이템 Name만 뽑아낸다.
(1) 체이닝의 문제점
- 체이닝을 사용하면 코드는 짧아지지만, 너무 길어지면 읽기 어렵고, 디버깅이 불편해질 수 있다. 따라서, 조건이 많아진다면 중간 변수로 나누는 것이 좋다.
5. LINQ를 사용하면 좋은 예시
1. 인벤토리 검색
2. 퀘스트 목록 필터링
3. 랭킹 정렬
4. UI에 보여줄 목록 정리
5. 상점 아이템 정렬
등등..
- 핵심은 특정 조건에 맞는 결과 목록을 뽑아야 할 때 적합하다.
6. LINQ에 대한 주의점 (★)
(1) Unity의 생명 주기 메서드에서는 사용을 조심해야 한다.
- Update에서 매 프레임 호출되는 코드
- FixedUpdate에서 반복적으로 호출되는 코드
- 위 두 개는 게임이 실행되는 동안 계속 반복 실행되는 코드다. Unity에서 Update()는 화면이 한 프레임 갱신될 때마다 실행되고, FixedUpdate()는 물리 처리용으로 반복 실행되는 함수다. 이러한 반복적으로 호출되는 함수안에 LINQ와 같은 작업을 넣으면 안된다.
Update()
{
var = targets = enemies.Where(enemy => enemy.IsAlive).ToList();
}
1. enemies를 처음부터 끝까지 하나씩 검사한다.
2. enemy.IsAlive 조건을 매번 확인한다.
3. 조건에 맞는 enmy를 새 List에 넣는다.
4. 그 List를 매 프레임 새로 만든다.
- 적이 100마리라면, 1프레임에 100번 검사.
- 60FPS이고, 적이 1000마리면, 60프레임. 즉, 1초에 60000번 검사하고, 그 만큼의 크기의 List를 만들게 된다. 여기에 ToList()까지 사용하면, 매 프레임마다 조건에 맞는 적들을 담기 위한 새로운 List가 만들어질 수 있다. (즉, 객체가 계속 만들어지는 것이다.)
- 즉, 핵심은 자주 반복되고, 객체 생성이 누적되는 코드 경로에서는 조심해야 한다.
7. 정리
※ LINQ는 컬렉션 데이터를 검색, 필터링, 정렬, 변환, 집계할 때 사용하는 기능이다. 코드를 짧고 읽기 쉽게 만들 수 있지만, 내부적으로는 데이터를 순회한다. 따라서 인벤토리 검색, 퀘스트 목록 필터링, UI 목록 정리처럼 가끔 실행되는 데이터 처리에는 적합하다.
'Unity > Unity 초격차캠프' 카테고리의 다른 글
| [20260520] Unity ( Unity의 기본 개념 ) (0) | 2026.05.20 |
|---|---|
| [20260519] C# 정리 ( 확장 메서드 ) (0) | 2026.05.19 |
| [20260519] C# 정리 ( Lambda Expression ) (0) | 2026.05.19 |
| [20260518] Git 용어 정리 (0) | 2026.05.18 |
| [20260518] C# ( Exception ) (0) | 2026.05.18 |