비트를 쪼개는 개발자

allen321@naver.com

C#

C# - System / Collections / Generic Collection

MozarTnT 2024. 6. 11. 16:18
728x90
반응형

 

 

 

 

C#으로 코딩할 때 맨 상단에 위치하는 using ~~~ 지시문은 해당 네임스페이스를 가져와서 사용하겠다는 의미로 사용한다.

 

 

 

내가 별도로 만든 프로젝트 파일의 네임스페이스를 가져와서 사용하기도 하지만 C#에서 자체적으로 지원하는 .NET의 기본 네임스페이스를 보통 많이 사용한다.

 

 

System

 

  • using System; 지시문을 사용해 선언한다.

 

 

  • using System 내에서 범용적으로 사용하는 클래스나 네임스페이스는 다음과 같다.

 

 

  • System.Console: 콘솔 입출력에 사용되는 클래스.
  • System.String: 문자열을 나타내는 클래스.
  • System.Int32, System.Double 등: 기본 데이터 타입을 나타내는 구조체.
  • System.Collections.Generic: 제네릭 컬렉션을 포함하는 서브 네임스페이스.
  • System.IO: 파일 및 데이터 스트림 입출력 클래스들을 포함하는 서브 네임스페이스.

 

 

 


 

Collections

 

 

  • using System.Collections 지시문을 사용해 선언한다.

 

  • 네임스페이스는 트리 구조로 조직화하는데, System이 루트 네임스페이스, Collections나 Collections.Generic이 서브 네임스페이스에 해당된다.

 

  • Collections는 주로 자료구조와 관련된 클래스들을 가지고 있다.

 

  • .Net 프레임워크에서 *비제네릭 컬렉션 클래스를 담당하는 대표적인 네임스페이스이다.

 

  • Generic Collection이 .Net 프레임워크 2.0에서 업데이트 된 후 자료구조에 제너릭이 지원된 이후로는 성능 문제로 자주 사용하지 않는 편이다.

 

 

 

비제네릭*이란?

 

- 타입 매개변수를 선언하지 않는 클래스이다.

- 다양한 데이터 타입에 사용할 수 있지만 타입 안전성이 보장되지 않기 떄문에 타입 캐스팅에 상당히 신경 써 주어야 한다.

- 박싱과 언박싱이 필수적이라 성능 측면에서 효율적이라고는 볼 수 없다.

 

 

 

Collections 내의 주요 클래스

 

각 자료구조에 대한 자세한 설명은 블로그 내에 자료구조 탭에서 자세히 설명하겠습니다.

 

1. ArrayList

 

  • 크기가 가변적인 배열이며 다양한 타입의 객체가 저장이 가능하다.
  • 인덱스를 사용해 요소(데이터)에 접근이 가능하다.
  • List와의 차이점은 자료형을 미리 선언하지 않아도 된다는 점이 있다.
using System;
using System.Collections;

class Program
{
    static void Main()
    {
        ArrayList arrayList = new ArrayList();
        arrayList.Add(10);
        arrayList.Add("hi");
        arrayList.Add(3.1);
    }
}

 

 

 

2.  Hashtable

 

 

 

  • 키 - 값 (key - value) 형식으로 데이터를 저장하는 자료구조이다.
  • Dictionary와는 다르게 key와 value 모두 어떤 타입이든 선언할 수 있다. 
  • 박싱과 언박싱이 일어난다.

 

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        Hashtable hashtable = new Hashtable();
        hashtable.Add("key1", "value1");
        hashtable.Add("key2", 2);
        hashtable.Add("key3", 3.0);
    }
}

 

 

 

3. Stack

 

 

  • LIFO(Last-In-First-Out) 방식으로 데이터를 저장하는 컬렉션이다.
  • Push로 요소를 추가하고, Pop으로 요소를 제거한다.
using System;
using System.Collections;

class Program
{
    static void Main()
    {
        Stack stack = new Stack();
        stack.Push("first");
        stack.Push("second");
        stack.Push("third");
    }
}

 

 

 

4. Queue

 

 

  • FIFO(First-In-First-Out) 방식으로 데이터를 저장하는 컬렉션이다.
  • Enqueue로 요소를 추가하고, Dequeue로 요소를 제거한다.
using System;
using System.Collections;

class Program
{
    static void Main()
    {
        Queue queue = new Queue();
        queue.Enqueue("one");
        queue.Enqueue("two");
        queue.Enqueue("three");
    }
}

 

 

 

 

 


 

 

 

Generic Collection

 

 

 

  • System.Collections.Generic 지시문을 사용해 선언한다.

 

  • Collections 에서는 데이터 타입을 명시하지 않았지만 Generic에서는 필수적으로 명시해야 한다.

 

  • 미리 데이터 타입을 정의하기 때문에 타입 안정성이 확보되며 컴파일 시간에 타임에 타입 검사를 수행해 런타임 오류가 줄어든다.

 

  • 박싱과 언박싱의 과정이 이루어지지 않기 때문에 성능이 올라간다.

 

 

 

 

Generic Collection 내의 주요 클래스

 

 

1. List<T>

List<T>에서 T는 제네릭 타입 매개변수(Type Parameter)를 의미함.

 

 

 

  • 가변 크기의 배열로, 배열과 유사하지만 크기를 동적으로 조정할 수 있다.
  • 인덱스를 사용하여 요소에 접근할 수 있다.
  • ArrayList와 유사하지만 데이터 타입을 명시해 주어야 한다.
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
        numbers.Add(8);
        numbers.Remove(3);
    }
}

 

 

 

 

 

2. Dictionary<TKey, TValue>

 

 

  • 키 - 값 (key - value) 형식으로 데이터를 저장하는 자료구조이다.
  • Hashtable과의 차이점은 Generic을 활용하여 객체를 생성하고 생성한 타입과 일치하는 타입만 데이터로 저장할 수 있다.
  • HashTable은 여러 타입을 활용 할 수 있다는 장점, Dictionary는 박싱과 언박싱이 없기 때문에 안정성과 속도가 빠르다는 장점이 있다.

 

 

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary<string, int> howOld = new Dictionary<string, int>();
        ages["Kim"] = 30;
        ages["Lee"] = 25;
        ages["Park"] = 40;
    }
}

 

 

 

3. Queue<T>, Stack<T>

 

  • Queue와 Stack은 LIFO(Last-In-First-Out) 방식, FIFO(First-In-First-Out) 방식을 사용한다는 자료구조임은 동일하다.
  • 다만 Queue와 Stack을 선언할때 사용할 자료형을 미리 명시해줘야 한다. 
  • ex) Queue<string> queue = new Queue<string>();
  • ex) Stack<int> stack = new Stack<int>();

 

 

 

4. HashSet<T>

 

  • 고유한 요소들을 저장하는 컬렉션으로, 중복된 데이터를 허용하지 않는다.
  • 데이터의 존재 여부를 빠르게 검사할 수 있다.
  • 데이터의 순서가 보장되지 않아서 순서가 중요한 데이터의 경우 다른 자료구조를 사용해야 한다.
  • 집합 연산과 관련된 기능들을 수행할 수 있다.

 

 

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        HashSet<int> numbers = new HashSet<int>();

        // 요소 추가
        numbers.Add(1);
        numbers.Add(2);
        numbers.Add(3);
        numbers.Add(1); // 중복 요소는 무시됨

        // 요소 확인
        Console.WriteLine(numbers.Contains(2));
        Console.WriteLine(numbers.Contains(4)); 

        // 요소 제거
        numbers.Remove(2);
    }
}

 

 

 

 

아래는 각종 집합 관련 연산을 수행하는 코드이다.

 

  • UnionWith(); 는 합집합을 반환한다.
  • IntetsectWith(); 는 교집합을 반환한다.
  • ExceptWith(); 는 차집합을 반환한다.

 

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        HashSet<int> set1 = new HashSet<int>() { 1, 2, 3, 4 };
        HashSet<int> set2 = new HashSet<int>() { 3, 4, 5, 6 };

        // 합집합
        set1.UnionWith(set2);
        Console.WriteLine("Union: " + string.Join(", ", set1)); // 1, 2, 3, 4, 5, 6

        // 교집합
        set1.IntersectWith(set2);
        Console.WriteLine("Intersection: " + string.Join(", ", set1)); // 3, 4

        // 차집합
        set1.ExceptWith(set2);
        Console.WriteLine("Difference: " + string.Join(", ", set1)); // 1, 2
    }
}
 

 

 

정리

 

  • using은 네임스페이스를 가져다 쓸때 사용한다.

 

  • using System; 은 System 네임스페이스에서 지원하는 여러 클래스나 형식을 가져다 쓴다는 뜻이다.

 

  • Collections과 Generic Collection은 자료구조의 형태가 비 제너릭과 제네릭이라는 차이점이 있다.

 

  • 비 제너릭 클래스는 데이터 타입을 명시하지 않아도 되서 편리하지만 박싱과 언박싱 과정에서 성능 저하와 데이터 타입 관련 캐스팅 오류가 발생할 확률이 높다.

 

  • 제네릭 클래스는 타입 안정성이 확보되며 성능이 올라간다. (일반적으로 제네릭을 많이 사용하게 된다.)

 

728x90
반응형