C# LINQ에서 Last()와 LastOrDefault()는 모두 조건에 일치하는 마지막 요소를 반환한다는 공통점이 있습니다. 하지만 두 메서드의 핵심적인 차이는 결과가 존재하지 않을 때의 동작 방식에 있습니다.
- Last(): 주어진 조건에 일치하는 요소가 없으면
InvalidOperationException예외를 발생시킵니다. - LastOrDefault(): 조건에 일치하는 요소가 없을 경우 예외를 던지지 않고 기본값(
null)을 반환합니다.
언제 어떤 메서드를 사용해야 할까?
Last()는 시퀀스에 최소한 하나 이상의 요소가 반드시 존재한다고 확신할 수 있을 때 사용하는 것이 좋습니다. 반면, 데이터의 존재 여부를 확신할 수 없다면 LastOrDefault()를 사용하여 예외 발생으로 인한 런타임 오류를 방지하는 것이 안전합니다.
예제 1: 요소가 존재하는 경우
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp {
public class Student {
public int Id { get; set; }
public string Name { get; set; }
}
class Program {
static void Main() {
var studentsList = new List<Student> {
new Student { Id = 1, Name = "John" },
new Student { Id = 2, Name = "Jack" },
new Student { Id = 1, Name = "Jill" }
};
var lastOrDefaultStudent = studentsList.LastOrDefault(student => student.Id == 1);
var lastStudent = studentsList.Last(student => student.Id == 1);
Console.WriteLine($"LastOrDefault: {lastOrDefaultStudent.Id} {lastOrDefaultStudent.Name}");
Console.WriteLine($"Last: {lastStudent.Id} {lastStudent.Name}");
Console.ReadLine();
}
}
}실행 결과
LastOrDefault: 1 Jill Last: 1 Jill
위 코드에서는 Id == 1인 학생이 목록에 존재하므로, 두 메서드 모두 해당 조건과 일치하는 마지막 요소인 "Jill"을 정상적으로 반환합니다.
예제 2: 요소가 존재하지 않는 경우
using System;
using System.Collections.Generic;
using System.Linq;
namespace DemoApplication {
public class Student {
public int Id { get; set; }
public string Name { get; set; }
}
class Program {
static void Main(string[] args) {
try {
var studentsList = new List<Student> {
new Student { Id = 1, Name = "John" },
new Student { Id = 2, Name = "Jack" }
};
// Id가 3인 학생은 존재하지 않음
var lastOrDefaultStudent = studentsList.LastOrDefault(student => student.Id == 3);
var value = lastOrDefaultStudent == null ? "null" : "";
Console.WriteLine($"LastOrDefault: {value}");
// Last() 호출 시 예외 발생
var lastStudent = studentsList.Last(student => student.Id == 3);
}
catch (Exception ex) {
Console.WriteLine($"Last Exception: {ex.Message}");
Console.ReadLine();
}
}
}
}실행 결과
LastOrDefault: null Last Exception: Sequence contains no matching element
위 예제에서 Id "3"에 해당하는 학생은 studentsList에 존재하지 않습니다. 따라서 LastOrDefault()는 예외 없이 null을 반환하는 반면, Last()는 "Sequence contains no matching element"라는 메시지와 함께 예외를 발생시킵니다.
정리
| 구분 | Last() | LastOrDefault() |
|---|---|---|
| 요소가 존재할 때 | 마지막 요소 반환 | 마지막 요소 반환 |
| 요소가 없을 때 | 예외 발생 (InvalidOperationException) | 기본값(null) 반환 |
| 권장 상황 | 데이터 존재가 보장될 때 | 데이터 존재 여부가 불확실할 때 |
결론적으로, 안정성이 중요한 실무 코드에서는 데이터 부재 가능성을 항상 고려하여 LastOrDefault()를 사용하고, 반환값의 null 여부를 확인하는 방어적 프로그래밍 습관을 갖추는 것이 좋습니다.