[C#] C# 컬렉션 (해시테이블, 딕셔너리), 제네릭, 인덱서 정리

한승호·2022년 6월 20일

C# 공부

목록 보기
6/13

C#컬렉션

리스트, 사전과 같은 대량의 데이터를 관리 및 제어할 수 있는 클래스를 의미한다. 배열, 리스트, 해시테이블 등과 같이 비슷한 성격을 가진 데이터를 모아놓는 자료구조를 컬렉션이라고 합니다.

C# 컬렉션 특징

  • C# 언어의 컬렉션은 모든 타입의 데이터를 보관하는 것이 가능하다.
  • C# 언어의 컬렉션은 내부적으로 Object 형으로 동작하기 때문에 값 형식의 데이터를 제어할 경우에는 박싱과 언박싱이라는 현상이 발생하며, 퍼포먼스의 저하가 발생한다.
  • 따라서 C#의 컬렉션은 Object 형을 기본으로 동작하도록 설계되어 있다.

이런 컬렉션을 더 편하게 사용하기 위해 foreach가 존재하는데, 이는 내부적으로 가비지 컬렉션을 유발하기 때문에 가능한 사용을 자제하는 것이 좋다. 따라서 퍼포먼스가 별도로 필요하지 않은 로직에서만 제한적으로 사용하는게 좋다.

퍼포먼스가 별도로 필요 없는 로직

  • 문자 + 문자열 + 옵션 값 세팅
  • 게임에서는 주로 환경 설정에 많이 사용한다.

C#해시테이블(HashTable

Key와 Value를 사용해 자료를 저장하는 자료구조로 빠르게 데이터를 검색할 수 있다.

  • Key 값을 Hash 함수에 넣어 코드 값으로 변경한 후 Bucket(배열)이라는 저장 공간에 인덱스 번호를 맵핑시켜 데이터를 저장한다.
  • 해시테이블은 각각의 key값에 해시 함수를 적용해 배열의 고유한 Index를 생성하고, 이 Index를 활용하여 값을 저장하거나 검색하는 곳에 사용이 된다.

해시테이블 특징

  • 제네릭을 사용하지 않는다.
  • Key와 Value 모두 Object를 입력받는다.
  • 박싱과 언박싱을 사용한다.
  • 자료형을 명시하지 않아도 된다.

따라서 해시테이블은 제네릭을 이용하지 않고, Object를 입력받기 때문에 모든 데이터 타입을 처리할 수 있지만,
입력과 출력에 박싱과 언박싱이 발생해 가비지 컬렉션을 유발한다.

C# 딕셔너리(Dictionary

딕셔너리 역시 Key와 Value를 사용해 자료를 저장하는 C#의 자료구조로 데이터에 대한 검색이 매우 빠르다.

딕셔너리 특징

  • 제네릭이다.
  • Key와 Value 모두 Strong Type을 입력받는다. -> 선언할 때 타입을 입력해주어야 한다는 말이다.
  • 박싱과 언박싱이 일어나지 않는다.
  • 자료형을 명시하기 때문에 형변환의 리스크가 없다.

HashTable과 Dictionary의 특징

  • 키를 가지고 빠르게 값에 접근하기에 좋다.
  • 순서나 중복되는 데이터가 있는 경우에는 사용으 고려한다면, 완벽한 판단 미스다!
  • 미리 저장공간을 확보하기 때문에 메모리 효율은 좋지 않다.
  • 평균적으로 제네릭을 사용하고 연산이 빠른 딕셔너리를 더 많이 사용하는 편
  • 해시테이블 보다 딕셔너리가 연산속도가 더 빠르다 -> 모든 타입을 받는지 아닌지에 대한 여부의 차이

해시테이블

  • Value에 일정한 형식이 없고, 여러 형태를 사용할 때

딕셔너리

  • 고정적으로 하나의 타입만 입력받을 때

둘 다 비슷한 사용법이지만, 내부적으로는 처리와 수용하는 타입의 형태가 다르기 때문에 어느 것을 사용할지 고민을 해야 한다.

C# 제네릭

C++의 템플릿과 마찬가지로 클래스 또는 메서드를 정의할 때, 타입을 지정하지 않고, 구현할 수 있는 매커니즘을 의미한다.

제네릭 특징

  • T와 같은 제네릭 타입을 명시하여 정의한다.
Class Test<T> //기본형

class Test<T> where T : class          (타입을 참조 형식으로 제한)
class Test<T> where T : struct         (타입을 값 형식으로 제한)
class Test<T> where T : SomeClass      (타입을 SomeClass를 직/간접적으로 상속하는 형식으로 제한)
class Test<T> where T : SomeInterface  (타입을 SomeInterface를 직/간접적으로 따르는 형식으로 제한)
class Test<T, U> where T : U           (타입을 U (클래스 or 인터페이스) 를 직/간접적으로 상속하는 형식으로 제한)
  • 모든 데이터 타입에 동작하도록 설계가 되어야 한다.
  • 제네릭 클래스 또는 메서드에 어떤 데이터 타입이 지정되어도 내부 로직에 변화가 발생하면 안된다.

C# 인덱서

C++의 인덱스 연산자 오버로딩과 같이 객체의 인덱스 연산을 시킬 때, 특정 함수를 호줄해 주는 매커니즘이다.
-> 객체를 배열처럼 사용할 수 있으며, 가독성이 좋고, 중복된 로직을 방지할 수 있다.

인덱서 특징

  • C# 언어의 인덱서는 this 키워드와 인덱스 연산자 ( [] )를 조합해서 정의하는 것이 가능하다.
  • C# 언어의 인덱서는 this 키워드를 통해서 정의되기 때문에 정적 클래스는 인덱서를 정의하는 것이 불가능하다.
  • C# 언어의 인덱서는 프로퍼티와 마찬가지로 get과 set을 통해서 로직을 정의하는 것이 가능하다.
  • C# 언어의 인덱서는 메서드와 마찬가지로 virtual과 override 키워드의 조합으로 오버라이드 매커니즘을 구현할 수 있다.
profile
모든 실수를 경험해 더 발전하고 싶은 개발자입니다.

0개의 댓글