[C# 문법] C# LINQ First, FirstOrDefault, Single, SingleOrDefault 차이점

참고

소개

  • 오늘은 C# LINQ 구문에서 First, FirstOrDefault, Single, SingleOrDefault 에 대한 차이점을 알려 드리려고 합니다.
  • 많은 사람들이 LINQ를 사용하면서 위의 구문들을 사용하기는 하지만, 어떠한 차이점이 있는지에 대해서는 완벽히 숙지하지 않고 사용하는 분들이 많은 것 같고, 저 또한 그랬기에 정리할 겸 차이를 설명해 드리도록 하겠습니다.

First() 메서드

  • 시퀀스의 첫 번째 요소를 반환합니다.
  • 결과에 요소가 없거나 소스가 null인 경우 오류가 발생합니다.
  • 둘 이상의 요소가 예상되면, 첫 번째 요소만 원하는 경우에 사용합니다.
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp7
{
    static class Program
    {
        static void Main(string[] args)
        {
            var result = InitialStudent().First();

            Console.WriteLine($"{result.Name} : {result.Age} : {result.Grade} : {result.Score}");

            var result2 = InitialStudent().First(x => x.Name == "범범조조2");
        }

        static List<Student> InitialStudent()
        {
            List<Student> list = new List<Student>()
            {
                new Student() { Name = "범범조조", Age = 20, Grade = "A", Score = 100 },
                new Student() { Name = "유재석", Age = 21, Grade = "B", Score = 10 },
                new Student() { Name = "김종국", Age = 22, Grade = "C", Score = 89 },
                new Student() { Name = "송지효", Age = 20, Grade = "D", Score = 60 },
                new Student() { Name = "하하", Age = 20, Grade = "A+", Score = 20 },
                new Student() { Name = "지석진", Age = 40, Grade = "F", Score = 55 },
                new Student() { Name = "아이유", Age = 30, Grade = "A", Score = 64 },
                new Student() { Name = "정형돈", Age = 20, Grade = "A", Score = 79 },
                new Student() { Name = "김성주", Age = 20, Grade = "A", Score = 29 }
            };

            return list;
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Grade { get; set; }
        public int Score { get; set; }
    }
}

실행 결과

범범조조 : 20 : A : 100
Unhandled exception. System.InvalidOperationException: Sequence contains no matching element
   at System.Linq.ThrowHelper.ThrowNoMatchException()
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
   at ConsoleApp7.Program.Main(String[] args) in C:\Users\상아\source\repos\ConsoleApp7\ConsoleApp7\Program.cs:line 15
  • First() 메서드를 사용시, 해당 비교값이 없다면 위의 결과와 같이 오류가 발생합니다.

FirstOrDefalut 메서드

  • 시퀀스의 첫 번째 요소를 반환하거나 요소가 없으면 기본값을 반환합니다.
  • 소스가 null인 경우에만 오류가 발생합니다.
  • 둘 이상의 요소가 예상되고 첫 번째 요소만 원하는 경우에 사용해야 합니다.
  • 결과가 비어 있어도 좋습니다.
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp7
{
    static class Program
    {
        static void Main(string[] args)
        {
            var result = InitialStudent().FirstOrDefault();

            Console.WriteLine($"{result.Name} : {result.Age} : {result.Grade} : {result.Score}");

            var result2 = InitialStudent().FirstOrDefault(x => x.Name == "범범조조2");
        }

        static List<Student> InitialStudent()
        {
            List<Student> list = new List<Student>()
            {
                new Student() { Name = "범범조조", Age = 20, Grade = "A", Score = 100 },
                new Student() { Name = "유재석", Age = 21, Grade = "B", Score = 10 },
                new Student() { Name = "김종국", Age = 22, Grade = "C", Score = 89 },
                new Student() { Name = "송지효", Age = 20, Grade = "D", Score = 60 },
                new Student() { Name = "하하", Age = 20, Grade = "A+", Score = 20 },
                new Student() { Name = "지석진", Age = 40, Grade = "F", Score = 55 },
                new Student() { Name = "아이유", Age = 30, Grade = "A", Score = 64 },
                new Student() { Name = "정형돈", Age = 20, Grade = "A", Score = 79 },
                new Student() { Name = "김성주", Age = 20, Grade = "A", Score = 29 }
            };

            return list;
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Grade { get; set; }
        public int Score { get; set; }
    }
}

실행 결과

범범조조 : 20 : A : 100
  • 오류가 발생하지 않지만, Student의 기본값을 반환합니다.

Single() 메서드

  • 시퀀스의 유일한 항목을 반환합니다.
  • 결과에 0개 이상의 요소가 포함된 경우 예외가 발생합니다.
  • 정확히 하나의 요소가 예상되지만 0이나 2 또는 그 이상이 아닌 것을 알고 있을 때 사용해야 합니다.
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp7
{
    static class Program
    {
        static void Main(string[] args)
        {
            var result2 = InitialStudent().Single(x => x.Score == 100);

            Console.WriteLine($"{result2.Name} : {result2.Age} : {result2.Grade} : {result2.Score}");

            var result = InitialStudent().Single(x => x.Age == 20);

            Console.WriteLine($"{result.Name} : {result.Age} : {result.Grade} : {result.Score}");
        }

        static List<Student> InitialStudent()
        {
            List<Student> list = new List<Student>()
            {
                new Student() { Name = "범범조조", Age = 20, Grade = "A", Score = 100 },
                new Student() { Name = "유재석", Age = 21, Grade = "B", Score = 10 },
                new Student() { Name = "김종국", Age = 22, Grade = "C", Score = 89 },
                new Student() { Name = "송지효", Age = 20, Grade = "D", Score = 60 },
                new Student() { Name = "하하", Age = 20, Grade = "A+", Score = 20 },
                new Student() { Name = "지석진", Age = 40, Grade = "F", Score = 55 },
                new Student() { Name = "아이유", Age = 30, Grade = "A", Score = 64 },
                new Student() { Name = "정형돈", Age = 20, Grade = "A", Score = 79 },
                new Student() { Name = "김성주", Age = 20, Grade = "A", Score = 29 }
            };

            return list;
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Grade { get; set; }
        public int Score { get; set; }
    }
}

실행 결과

범범조조 : 20 : A : 100
Unhandled exception. System.InvalidOperationException: Sequence contains more than one matching element
   at System.Linq.ThrowHelper.ThrowMoreThanOneMatchException()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
   at ConsoleApp7.Program.Main(String[] args) in C:\Users\상아\source\repos\ConsoleApp7\ConsoleApp7\Program.cs:line 15
  • 같은게 2개 이상 존재하면 Single() 메서드에서는 에러가 발생합니다.

SingleOrDefault() 메서드

  • 하나의 특정 요소를 반환하고 요소를 찾지 못하면 기본값을 반환합니다.
  • 결과에 2개 이상의 요소가 포함된 경우 예외가 발생합니다.
  • 결과로 0 또는 1개의 요소가 예상된다는 것을 알 때 사용해야 합니다.
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp7
{
    static class Program
    {
        static void Main(string[] args)
        {
            var result2 = InitialStudent().SingleOrDefault(x => x.Score == 100);

            Console.WriteLine($"{result2.Name} : {result2.Age} : {result2.Grade} : {result2.Score}");

            var result = InitialStudent().SingleOrDefault(x => x.Age == 33);
        }

        static List<Student> InitialStudent()
        {
            List<Student> list = new List<Student>()
            {
                new Student() { Name = "범범조조", Age = 20, Grade = "A", Score = 100 },
                new Student() { Name = "유재석", Age = 21, Grade = "B", Score = 10 },
                new Student() { Name = "김종국", Age = 22, Grade = "C", Score = 89 },
                new Student() { Name = "송지효", Age = 20, Grade = "D", Score = 60 },
                new Student() { Name = "하하", Age = 20, Grade = "A+", Score = 20 },
                new Student() { Name = "지석진", Age = 40, Grade = "F", Score = 55 },
                new Student() { Name = "아이유", Age = 30, Grade = "A", Score = 64 },
                new Student() { Name = "정형돈", Age = 22, Grade = "A", Score = 79 },
                new Student() { Name = "김성주", Age = 20, Grade = "A", Score = 29 }
            };

            return list;
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Grade { get; set; }
        public int Score { get; set; }
    }
}

실행 결과

범범조조 : 20 : A : 100
  • 현재 나이가 33인 학생은 없지만, 예외가 발생하지 않는 것을 확인할 수 있습니다.

정리

  • 예외처리 신경쓰고 싶다면, FirstOrDefault, SingleOrDefault를 사용하는걸 추천 드립니다.
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY