Home [고급 C#] LINQ #1
Post
Cancel

[고급 C#] LINQ #1

LINQ

C#에서는 LINQ라는 기능을 지원해주고 있다.
LINQ는 “Language-Integrated Query”의 약자로, Query를 통해 원하는 데이터를 빠르고 편리하게 추출 할 수 있는 기능이다.
데이터를 다룰 때 유용한 문법이며, SQL 문법과 비슷하다.

보통 데이터들이 있을 때 거기서 특정 필요한 데이터만 추출 및 가공해서 사용해야 하는 경우가 있다. 이때 기본적으로 for, if 문으로도 할 수 있지만 LINQ를 사용할 경우 가독성을 높일 수 있고 빠르고 편리하게 사용할 수 있다.

LINQ 사용법

예를 들어 수많은 player들의 데이터들이 있다고 할 때
레벨이 50 이상이고 직업이 Knight인 player들만 오름차순(레벨)으로 정렬해서 가져와야 한다면

기본 C# 문법으로만 처리(for, if 문)

먼저 기본적인 C#문법으로만 처리해보자.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public enum ClassType
{
    Knight,
    Archer,
    Mage
}

public class Player
{
    public ClassType classType { get; set; }
    public int Level { get; set; }
    public int Hp { get; set; }
    public int Attack { get; set; }
}

class Program
{
    static List<Player> _players = new List<Player>();

    static void Main(String[] args)
    {
        Random rand = new Random();

        // player 데이터 100개 랜덤 생성
        for (int i = 0; i < 100; i++)
        {
            ClassType type = ClassType.Knight;
            switch (rand.Next(0, 3))
            {
                case 0:
                    type = ClassType.Knight;
                    break;
                case 1:
                    type = ClassType.Archer;
                    break;
                case 2:
                    type = ClassType.Mage;
                    break;
            }

            Player player = new Player()
            {
                classType = type,
                Level = rand.Next(1, 100),
                Hp = rand.Next(100, 1000),
                Attack = rand.Next(5, 50)
            };

            _players.Add(player);
        }

        // 레벨이 50 이상인 Knight만 추려내서, 오름차순(레벨)으로 정렬
        List<Player> players = GetHighLevelKnights();
        foreach(Player p in players)
        {
            Console.WriteLine($"{p.Level} {p.Hp}");
        }
    }

    static List<Player> GetHighLevelKnights()
    {
        List<Player> players = new List<Player>();

        foreach(Player player in _players)
        {
            if (player.classType != ClassType.Knight)
                continue;
            if (player.Level < 50)
                continue;

            players.Add(player);
        }

        players.Sort((a, b) => { return a.Level - b.Level; });

        return players;
    }
}

이때 원하는 데이터를 추출하는 부분은 GetHighLevelKnights()이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static List<Player> GetHighLevelKnights()
{
    List<Player> players = new List<Player>();

    foreach(Player player in _players)
    {
        if (player.classType != ClassType.Knight)
            continue;
        if (player.Level < 50)
            continue;

        players.Add(player);
    }

    players.Sort((a, b) => { return a.Level - b.Level; });

    return players;
}

지금은 간단한 처리만 해주고 있다보니 그렇게 막 복잡하지는 않지만 아무런 조건도 모른채로 이 코드만 보았을 때 어떤 데이터를 추출하고 있는지 한번에 해석하기는 쉽지 않을 것이다.

LINQ를 사용하여 처리

LINQ의 기본 문법은 아래와 같다.

from 어떤 데이터에서 찾을 것인지
where 어떤 조건으로 찾을 것인지
orderby 어떤 항목을 기준으로 정렬할 것인지
select 어떤 항목을 추출할 것인지

LINQ를 사용해서 위와 똑같은 작업을 해보자.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public enum ClassType
{
    Knight,
    Archer,
    Mage
}

public class Player
{
    public ClassType classType { get; set; }
    public int Level { get; set; }
    public int Hp { get; set; }
    public int Attack { get; set; }
}

class Program
{
    static List<Player> _players = new List<Player>();

    static void Main(String[] args)
    {
        Random rand = new Random();

        // player 데이터 100개 랜덤 생성
        for (int i = 0; i < 100; i++)
        {
            ClassType type = ClassType.Knight;
            switch (rand.Next(0, 3))
            {
                case 0:
                    type = ClassType.Knight;
                    break;
                case 1:
                    type = ClassType.Archer;
                    break;
                case 2:
                    type = ClassType.Mage;
                    break;
            }

            Player player = new Player()
            {
                classType = type,
                Level = rand.Next(1, 100),
                Hp = rand.Next(100, 1000),
                Attack = rand.Next(5, 50)
            };

            _players.Add(player);
        }

        // 레벨이 50 이상인 Knight만 추려내서, 레벨 오름차순으로 정렬
        // LINQ 문법
        var players =
            from p in _players
            where p.classType == ClassType.Knight && p.Level >= 50
            orderby p.Level ascending // ascending은 생략가능, 내림차순은 desecnding
            select p;

        foreach (Player p in players)
        {
            Console.WriteLine($"{p.Level} {p.Hp}");
        }
    }
}

LINQ 부분을 보자면 이전 코드의 GetHighLevelKnights()부분과 같은 역할을 하고 있음을 알 수 있다.

1
2
3
4
5
var players =
    from p in _players
    where p.classType == ClassType.Knight && p.Level >= 50
    orderby p.Level ascending // ascending은 생략가능, 내림차순은 desecnding
    select p;

SQL을 배웠다면 SQL문법과 매우 비슷하기에 쉽게 사용할 수 있을 것이다.
또한 이전 코드에 비해 짧고 가독성이 좋아 데이터를 다룰 때 유용하게 사용할 수 있다.

This post is licensed under CC BY 4.0 by the author.