[C# 기초문법] 6. 컬렉션(Collection)
배열(Array)
C#에서는 배열을 다음과 같이 사용합니다.
(2차원 배열의 예)
코드로 보면 다음과 같습니다.
{
{1, 2},
{2, 3},
{3, 4}
};
또, 가변배열(Jagged Array)도 있습니다. 배열을 요소로 갖는 배열입니다.
코드로 보면 다음과 같습니다.
jaggedarray[0]= new int[5] {1,2,3,4,5};
jaggedarray[1]= new int[3] {10,20,30};
jaagedarray[2]= new int[2] {100,200};
컬렉션(Collection)
컬렉션이란, 같은 성격을 띠는 데이터의 모음을 담는 자료구조를 말합니다.
보통 같은 성격의 데이터의 묶음들을 배열로 만들어서 사용했지만, C#은 컬렉션이라는 개념으로 배열뿐만 아니라, ArrayList, Queue, Stack, Hashtable 등 여러가지 컬렉션 클래스를 제공합니다. (System.Collections)
이중에서 Hashtable만 사용해보겠습니다.
Hashtable은 Key와 Value가 쌍으로 이루어진 데이터를 다룰때 사용합니다.
자료구조에서도 배우겠지만, 해싱으로 아주 빠른 탐색속도를 자랑합니다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; namespace CsharpStudy { class Program { static void Main(string[] args) { Hashtable Ht = new Hashtable(); Ht["하나"] = "One"; Ht["둘"] = "Two"; Ht["셋"] = "Three"; Console.WriteLine("요소 직접 접근: {0}", Ht["셋"]); Console.WriteLine("==Hashtable의 모든 데이터 접근=="); foreach(var value in Ht.Values) { Console.WriteLine(value); } Console.WriteLine("==Hashtable의 모든 Key 접근=="); foreach (var key in Ht.Keys) { Console.WriteLine(key); } } } }
인덱서(Indexer)
인덱스를 이용하여 객체 내의 데이터에 접근하게 할 수 있습니다.
인덱서를 선언하는 형식은 다음과 같습니다.
{
한정사 인덱서형식 this[형식 index]
{
get
{
// index를 이용하여 내부 데이터 반환
}
set
{
// index를 이용하여 내부 데이터 저장
}
}
}
코드를 보겠습니다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; namespace CsharpStudy { class MyList { private int[] array; public MyList() { this.array = new int[3]; } public int this[int index] { get { return array[index]; } set { if(index >= array.Length) { Array.Resize(ref array, index + 1); //무시하세요 태그때문에 Console.WriteLine("array resized : {0}", array.Length); } array[index] = value; } } public int Length { get { return array.Length; } } } class Program { static void Main(string[] args) { MyList mylist = new MyList(); Console.WriteLine("==데이터 저장=="); for(int i=0; i<5; i++) { mylist[i] = i; } Console.WriteLine("==데이터 출력=="); for (int i = 0; i < mylist.Length; i++) // foreach를 사용할 수 없습니다. { Console.WriteLine(mylist[i]); } } } }
위와 Mylist라는 객체에 대한 데이터를 인덱스로 접근할 수 있게 만들었습니다.
하지만, 조금만 생각해보면 foreach문은 불가능하다는 사실을 깨닫습니다. 그 이유는
Mylist라는 객체만 보고 요소하나하나를 어떻게 판단할 것이며, 어떻게 순회할지에 대한 약속이 전혀 없기 때문입니다.
그렇다면 foreach문이 가능한 객체는 어떻게 만들 수 있을까요?
foreach문이 가능한 객체만들기
foreach문이 가능하기 위해서는 IEnumerable, IEnumerator 를 상속받아야 합니다.
즉, IEnumerable, IEnumerator 를 구현하면서 약속을 정해주어야하는 것입니다.
IEnumerable
메소드 |
설명 |
IEnumerator GetEnumerator() |
IEnumerator 형식의 객체를 반환 |
IEnumerator
메소드 |
설명 |
boolean MoveNext() |
다음 요소로 이동합니다. 컬렉션의 끝을 지난 경우에는 false, 이동이 성공한 경우에는 true를 반환합니다. |
void Reset() |
컬렉션의 첫 번째 위치의 '앞'으로 이동합니다. 첫번째 위치가 0번째라면 -1번으로 이 동합니다. MoveNext()를 호출한 다음에 이루어집니다. |
Object Current { get; } |
컬렉션의 현재 요소를 반환합니다. |
위 인터페이스를 상속받아 구현해보겠습니다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; namespace CsharpStudy { class MyList : IEnumerable , IEnumerator { private int[] array; int position = -1; public MyList() { this.array = new int[3]; } public int this[int index] { get { return array[index]; } set { if(index >= array.Length) { Array.Resize(ref array, index + 1); //무시하세요 태그문제때문에 Console.WriteLine("array resized : {0}", array.Length); } array[index] = value; } } public object Current { get { return array[position]; } } public void Reset() { position = -1; } public bool MoveNext() { if( position == array.Length -1) { Reset(); return false; } position++; return (position < array.Length); } public IEnumerator GetEnumerator() { for(int i=0; i <array.Length; i++) { yield return (array[i]); } } } class Program { static void Main(string[] args) { MyList mylist = new MyList(); Console.WriteLine("==데이터 저장=="); for(int i=0; i<5; i++) { mylist[i] = i; } Console.WriteLine("==데이터 출력=="); foreach(var item in mylist) // foreach가 가능해졌습니다. { Console.WriteLine(item); } } } }
이상으로 컬렉션에 대해 정리해보았습니다.
<참고문헌>
뇌를 자극하는 C# 4.0 프로그래밍 - 박상현 저