Languague/C# / / 2025. 4. 13. 08:00

[C# LINQ] 정렬 + 조건 필터 사용법 및 MaxBy/MinBy (InvalidOperationException, NullReferenceException 해결법)

300x250

 

LINQ를 사용할 때 데이터를 정렬하거나 조건에 맞게 필터링하는 것은 매우 자주 필요한 기능이다. 특히 OrderBy, Where와 함께 MaxBy()MinBy()를 활용하면, 원하는 요소를 쉽게 뽑아낼 수 있다. 막상 사용하다 보면 InvalidOperationException이나 NullReferenceException과 같은 오류가 발생하는 경우가 많습니다. 이번 글에서는 정렬 및 조건 필터 기본 사용법과 함께, MaxBy/MinBy 사용 시 자주 발생하는 오류 및 해결법을 알아보려고한다.


📚 목차

1. 정렬 및 조건 필터 기본

2. MaxBy/MinBy 사용법

3. 자주 발생하는 오류와 해결법

4. 실전 예제: 상품 리스트 처리


1. 정렬 및 조건 필터 기본

LINQ에서 OrderByWhere를 사용하면 데이터를 정렬하고 특정 조건에 맞게 필터링할 수 있다.

예를 들어, 주문 리스트에서 주문 날짜가 특정 기간에 해당하는 데이터만 뽑거나, 제품 가격 기준으로 정렬하는 등의 작업을 할 수 있다.


// 기본 예제: 주문 데이터를 날짜 기준으로 정렬하고, 특정 날짜 이후 주문만 필터링
var filteredOrders = orders
    .Where(o => o.OrderDate >= new DateTime(2023, 1, 1))
    .OrderBy(o => o.OrderDate);

 

위 코드는 주문 날짜가 2023년 1월 1일 이후인 주문들을 날짜 순으로 정렬한다.


2. MaxBy/MinBy 사용법

.NET 6부터는 MaxBy()MinBy()를 사용해 컬렉션 내에서 최대값/최소값 요소를 쉽게 뽑아낼 수 있다.

예를 들어, 상품 리스트에서 가장 비싼 제품이나 가장 최근에 등록된 제품을 찾을 때 유용하다.


// 예제: 상품 리스트에서 가장 높은 가격의 제품 찾기
var mostExpensiveProduct = products.MaxBy(p => p.Price);

// 예제: 주문 리스트에서 가장 최근 주문 찾기
var latestOrder = orders.MaxBy(o => o.OrderDate);

위 코드는 각각 최대 가격과 최대 주문 날짜를 기준으로 해당 요소를 반환한다.


3. 자주 발생하는 오류와 해결법

LINQ 정렬 및 집계 관련해서 자주 발생하는 오류는 다음과 같다:

❌ 오류 1: InvalidOperationException

예: 조건에 맞는 요소가 하나도 없을 때 MaxBy()MinBy()를 사용하면 발생한다.


System.InvalidOperationException: Sequence contains no elements.

 

해결 방법: DefaultIfEmpty()를 사용해 빈 시퀀스에 기본값을 제공하거나, ?? 연산자로 결과가 없을 경우 대체값을 지정한다.


// DefaultIfEmpty() 사용 예제
var mostExpensive = products
    .Where(p => p.Price.HasValue && p.Price > 1500) // 조건에 맞는 데이터 없음
    .DefaultIfEmpty(new Product { Name = "없음", Price = 0 })
    .MaxBy(p => p.Price);

Console.WriteLine($"Result: {mostExpensive.Name}, {mostExpensive.Price}"); // "없음, 0"

// ?? 연산자 사용 예제
var mostExpensiveWithNullCoalescing = products
    .Where(p => p.Price.HasValue && p.Price > 1500)
    .MaxBy(p => p.Price) ?? new Product { Name = "없음", Price = 0 };

Console.WriteLine($"Result: {mostExpensiveWithNullCoalescing.Name}, {mostExpensiveWithNullCoalescing.Price}"); // "없음, 0"

 

DefaultIfEmpty()는 시퀀스가 비었을 때 기본 요소를 추가하고, ??는 결과가 null일 때 대체값을 제공한다.

❌ 오류 2: NullReferenceException

예: 정렬 기준이 되는 속성이 null일 경우 발생할 수 있다.


var result = products.OrderBy(p => p.Price).First().ToString(); // 만약 Price가 null이면 오류 발생

 

해결 방법: 정렬 전 null 여부를 체크하거나, ?? 연산자를 사용해 기본값을 지정한다.


// null 체크 후 정렬
var safeResult = products
    .Where(p => p.Price.HasValue) // null 제외
    .OrderBy(p => p.Price)
    .First()
    .ToString();

// ?? 연산자로 기본값 지정
var priceOrDefault = products.MaxBy(p => p.Price)?.ToString() ?? "가격 정보 없음";

 

→ null 체크와 기본값 지정을 통해 예외를 방지할 수 있다.


4. 실전 예제: 상품 리스트 처리

예제 상황: 상품 리스트에서 가격이 0보다 큰 상품 중, 가장 높은 가격의 제품을 찾고, 그 결과를 조건에 따라 필터링해서 보여준다.

🧾 데이터 정의


public class Product
{
    public string Name { get; set; }
    public decimal? Price { get; set; }
    public DateTime RegisteredAt { get; set; }
}

var products = new List
{
    new Product { Name = "노트북", Price = 1200, RegisteredAt = new DateTime(2023, 1, 10) },
    new Product { Name = "모니터", Price = 800, RegisteredAt = new DateTime(2023, 2, 5) },
    new Product { Name = "키보드", Price = null, RegisteredAt = new DateTime(2023, 3, 1) },
    new Product { Name = "마우스", Price = 300, RegisteredAt = new DateTime(2023, 1, 20) }
};

🧾 LINQ 코드


// Price가 null이 아닌 상품들 중, 가격이 0보다 큰 것 필터링 후 가장 비싼 제품 찾기
var mostExpensive = products
    .Where(p => p.Price.HasValue && p.Price > 0)
    .MaxBy(p => p.Price) ?? new Product { Name = "없음", Price = 0 };

var result = mostExpensive;

📌 예상 출력 결과


Product Name: 노트북, Price: 1200, RegisteredAt: 2023-01-10

→ Price가 null인 제품은 제외되고, 가장 높은 가격을 가진 "노트북"이 결과로 나온다.


5. 마무리

정렬과 조건 필터는 실무에서 데이터를 효과적으로 가공하는 데 필수적인 기능이다.
OrderBy, Where, 그리고 MaxBy()/MinBy()를 적절히 활용하면 원하는 데이터를 쉽게 뽑아낼 수 있다.

  • InvalidOperationException: 조건에 맞는 데이터가 없으면 발생. DefaultIfEmpty()로 빈 시퀀스에 기본값을 제공하자.
  • NullReferenceException: 정렬 기준 null 체크 필수. ?? 연산자로 기본값을 지정하면 안전하다.
  • 예제처럼 DefaultIfEmpty()는 시퀀스 수준에서, ??는 개별 결과 수준에서 활용 가능.

 

300x250
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유