[C# – 기초 강좌] 6. 고급 데이터 타입 및 자료구조 (Collection)

C#은 객체 지향 프로그래밍 언어로 다양한 고급 데이터 타입(Data type)과 자료구조(Collection)를 제공하여 데이터를 효율적으로 관리할 수 있게 해줍니다.

이번 포스트에서는 C#에서 사용할 수 있는 몇 가지 기본적인 고급 데이터 타입들인 리스트(List), 열거형(Enum), 구조체(Structure)에 대해 알아보고, LINQ(Language Integrated Query)의 기초에 대해서도 살펴보겠습니다.

자료구조 (Collection)

자료구조, 특히 프로그래밍에서의 컬렉션(Collection)은 데이터를 효율적으로 저장하고 관리하기 위한 구조를 의미합니다.

컬렉션은 다양한 데이터 아이템들을 조직화, 관리, 저장하고, 이 데이터에 접근하고 수정할 수 있는 방법을 제공합니다.

자료구조는 배열(Array), 리스트(List), 큐(Queue), 스택(Stack), 세트(Set), 해시 테이블(Hash Table), 트리(Tree), 그래프(Graph) 등과 같이 여러 형태가 있으며, 각각은 특정 타입의 작업을 처리하는 데 최적화되어 있습니다.

collection-data-structure-images

사용이유

  1. 효율성:
    • 컬렉션은 데이터를 효율적으로 관리하도록 설계되어 있습니다.
    • 예를 들어, 배열은 인덱스를 사용하여 빠른 접근 속도를 제공하고, 링크드 리스트는 요소의 추가와 삭제가 용이하도록 구성됩니다.
  2. 유연성:
    • 데이터의 크기나 유형에 따라 가장 적합한 자료구조를 선택할 수 있습니다.
    • 동적 배열인 리스트는 크기 조정이 자유롭고, 해시 테이블은 키를 사용한 빠른 검색을 제공합니다.
  3. 재사용성과 유지보수:
    • 컬렉션은 일반적으로 잘 정의된 인터페이스와 메소드를 제공하여, 데이터 관리 로직을 간소화하고 재사용 가능하게 합니다.
    • 이는 코드의 유지보수와 오류 수정을 용이하게 만들어 줍니다.
  4. 안정성:
    • 표준 라이브러리에서 제공하는 자료구조들은 대체로 테스트와 최적화가 잘 되어 있어, 자체적으로 자료구조를 구현할 때 발생할 수 있는 오류의 가능성을 줄여 줍니다.

자료구조(Collection) 종류

배열 (Array)

배열은 같은 타입의 요소를 일련의 연속된 메모리 공간에 저장합니다.

크기가 고정되어 있으며, 각 요소는 인덱스를 통해 접근할 수 있습니다.

            int[] numbers = new int[3];
            numbers[0] = 2;
            numbers[1] = 4;
            numbers[2] = 6;
            foreach (int number in numbers)
            {
                Console.WriteLine(number);
            }

리스트 (List)

리스트는 크기가 동적으로 변하는 배열과 유사한 컬렉션입니다.

요소의 추가 및 삭제가 자유로우며, List<T> 클래스를 사용하여 구현됩니다.

            List<string> fruits = new List<string>();
            fruits.Add("Apple");
            fruits.Add("Banana");
            fruits.Add("Cherry");
            foreach (string fruit in fruits)
            {
                Console.WriteLine(fruit);
            }

큐 (Queue)

큐는 FIFO (First In, First Out) 정책을 따르는 컬렉션으로, 요소가 추가된 순서대로 접근 및 삭제됩니다.

            Queue<int> queue = new Queue<int>();
            queue.Enqueue(1);
            queue.Enqueue(2);
            queue.Enqueue(3);

            while (queue.Count > 0)
            {
                Console.WriteLine(queue.Dequeue());
            }

스택 (Stack)

스택은 LIFO (Last In, First Out) 정책을 따르는 컬렉션으로, 가장 최근에 추가된 요소가 가장 먼저 제거(Pop)됩니다.

            Stack<string> stack = new Stack<string>();
            stack.Push("First");
            stack.Push("Second");
            stack.Push("Third");
            
            while (stack.Count > 0)
            {
                Console.WriteLine(stack.Pop());
            }

세트 (Set)

세트는 중복을 허용하지 않는 요소들의 컬렉션입니다.

HashSet<T> 클래스를 사용하여 구현되며, 요소의 유일성이 보장됩니다.

            HashSet<int> numbersSet = new HashSet<int>();
            numbersSet.Add(1);
            numbersSet.Add(1); // Ignore duplicate value
            numbersSet.Add(2);
            foreach (int number in numbersSet)
            {
                Console.WriteLine(number);
            }

딕셔너리(Dictionary)

딕셔너리(Dictionary)는 키(Key)를 값(Value)에 매핑하여 데이터를 저장하는 컬렉션입니다.

Dictionary<TKey, TValue> 클래스를 사용하여 구현됩니다.

Hash Table과 같습니다.

            Dictionary<string, string> capitals = new Dictionary<string, string>();
            capitals.Add("France", "Paris");
            capitals.Add("Italy", "Rome");
            capitals.Add("Japan", "Tokyo");
            foreach (KeyValuePair<string, string> item in capitals)
            {
                Console.WriteLine($"The capital of {item.Key} is {item.Value}");
            }

사용 시기 및 용도

자료구조사용 시기 및 용도
배열 (Array)요소의 개수가 고정되어 있고, 인덱스를 통한 빠른 접근이 필요할 때 사용합니다.
리스트 (List)요소의 개수가 변동될 수 있으며, 동적으로 요소를 추가하거나 삭제해야 할 때 유용합니다.
큐 (Queue)데이터를 순차적으로 처리해야 하고, 먼저 들어온 데이터를 먼저 처리해야 하는 FIFO (First In, First Out) 정책을 따를 때 사용합니다.
스택 (Stack)데이터를 역순으로 처리해야 하고, 마지막에 들어온 데이터를 먼저 처리해야 하는 LIFO (Last In, First Out) 정책을 따를 때 사용합니다.
세트 (Set)중복을 허용하지 않고, 요소의 유일성을 보장해야 할 때 사용합니다. 빠른 검색과 요소의 존재 여부 확인이 필요할 때 유용합니다.
딕셔너리(Dictionary)키를 통한 빠른 데이터 접근이 필요할 때 사용합니다. 데이터를 키와 값의 쌍으로 저장하고, 키를 사용하여 빠르게 데이터를 검색할 수 있습니다.

열거형(Enum)과 구조체(Structure)

열거형(Enum)

열거형(Enum)은 관련된 상수들을 함께 그룹화하여 코드의 가독성을 높이고 오류를 줄이는 데 도움을 줍니다.

열거형은 기본적으로 int 형으로 처리되며, 각 항목의 기본 값은 0부터 시작하여 순차적으로 증가합니다.

    enum Day { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

    Day today = Day.Wednesday;
    Console.WriteLine($"Today is {today} {((int)today)}");

구조체 (Structure)

구조체는 관련된 여러 데이터를 하나의 단위로 묶을 때 사용합니다.

클래스와 유사하지만, 구조체는 값 타입이며 스택에 할당됩니다.

이는 구조체가 메모리를 더 효율적으로 사용할 수 있게 하며, 간단한 데이터 구조를 표현할 때 유용합니다.

struct Point {
    public int X;
    public int Y;

    public Point(int x, int y) {
        X = x;
        Y = y;
    }
}

Point point = new Point(10, 20);
Console.WriteLine($"Point coordinates: ({point.X}, {point.Y})");

LINQ(Language Integrated Query)

소개

LINQ(Language Integrated Query)는 C#을 비롯한 .NET 언어에서 제공하는 강력한 데이터 쿼리 기능입니다.

이 기능을 통해 개발자는 데이터베이스, 배열, 컬렉션, XML 등 다양한 데이터 소스에 대해 일관된 방식으로 쿼리를 작성할 수 있습니다.

LINQ는 코드를 더욱 간결하고 읽기 쉽게 만들어, 데이터 처리와 관련된 작업을 효율적으로 할 수 있게 돕습니다.

장점

  1. 일관된 쿼리 언어: 다양한 데이터 소스에 대해 동일한 쿼리 구문을 사용할 수 있습니다.
  2. 코드의 간결성과 가독성 향상: 복잡한 쿼리도 몇 줄의 코드로 표현할 수 있습니다.
  3. 컴파일 타임 검증: 쿼리 실수를 런타임 이전에 발견할 수 있습니다.
  4. 디버깅 용이: 표준 .NET 디버깅 도구를 사용하여 LINQ 쿼리를 쉽게 디버깅할 수 있습니다.

사용방법

LINQ를 사용하는 기본적인 방법은 두 가지 형태로 나뉩니다:

  • 쿼리 신택스(Query Syntax): SQL에 가깝게 작성된다.
  • 메서드 신택스(Method Syntax): 확장 메서드를 사용한 람다 표현식을 기반으로 합니다.
쿼리 신택스(Query Syntax)

다음과 같이 SQL의 from, where, select 를 이용하여 데이터를 관리할 수 있습니다.

            int[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            var evenNumbers = from num in nums
                              where num % 2 == 0
                              select num;

            foreach (var num in evenNumbers)
            {
                Console.WriteLine(num); // Outputs even numbers: 0, 2, 4, 6, 8
            }
메서드 신택스(Method Syntax)

다음과 같이 확장된 메서드 Where()을 이용하여 데이터를 관리할 수 있습니다.

            var oddNumbers = nums.Where(n => n % 2 == 1);
            foreach (var num in oddNumbers)
            {
                Console.WriteLine(num); // Outputs odd numbers: 1, 3, 5, 7, 9
            }

참고 링크

Leave a Comment

Discover more from Devitworld

Subscribe now to keep reading and get access to the full archive.

Continue reading