배열(Array): 동일한 타입의 여러 데이터를 하나의 변수로 묶어 관리할 수 있는 자료 구조. 고정된 크기를 가지며, 순차적으로 저장된 데이터에 인덱스를 통해 접근할 수 있음.

 

특징

  • 동일한 데이터 타입: 배열은 하나의 데이터 타입만 저장할 수 있어, 타입 안전성을 유지할 수 있음.
  • 고정된 크기: 배열의 크기는 초기화 시점에 고정되며, 이후에는 변경할 수 없음.
  • 인덱스를 통한 접근: 배열 요소는 0부터 시작하는 인덱스를 통해 개별적으로 접근할 수 있음.
  • 연속된 메모리: 배열 요소는 메모리에 연속적으로 저장되어, 데이터 접근 속도가 빠름.

배열의 선언과 초기화: 타입 뒤에 대괄호([])를 추가하여 선언하며, 초기화는 중괄호({})를 사용하거나 new 키워드를 사용하여 할 수 있음.

// 정수형 배열 선언과 초기화
int[] numbers = { 1, 2, 3, 4, 5 };

// 또는 new 키워드 사용
int[] scores = new int[5]; // 크기가 5인 배열 생성, 기본값 0으로 초기화
scores[0] = 10; // 첫 번째 요소에 값 설정
scores[1] = 20;

 

배열 요소 접근과 수정: 인덕스를 통해 접근하며, 인덕스를 통해 값을 수정할 수도 있음.

int[] numbers = { 1, 2, 3, 4, 5 };

// 배열 요소 접근
Console.WriteLine(numbers[0]); // 출력: 1
Console.WriteLine(numbers[2]); // 출력: 3

// 배열 요소 수정
numbers[2] = 10;
Console.WriteLine(numbers[2]); // 출력: 10

 

배열의 길이 확인: Length 속성을 사용하여 확인할 수 있음.

int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine(numbers.Length); // 출력: 5

 

 

다차원 배열: 배열은 2차원 이상의 다차원 배열로 선언할 수 있음. 다차원 배열은 행과 열로 이루어지며, 2차원 배열은 주로 테이블 형태의 데이터를 저장할 때 유용함.

// 2차원 배열 선언 및 초기화
int[,] matrix = { { 1, 2 }, { 3, 4 }, { 5, 6 } };

// 요소 접근
Console.WriteLine(matrix[0, 0]); // 출력: 1
Console.WriteLine(matrix[2, 1]); // 출력: 6

 

장점과 단점

  • 빠른 데이터 접근: 배열 요소는 인덱스를 통해 빠르게 접근할 수 있음.
  • 메모리 효율성: 배열은 메모리에 연속적으로 저장되므로, 데이터 접근과 관리를 효율적으로 수행할 수 있음.
  • 반복문을 통한 처리 용이: 배열은 반복문을 통해 모든 요소에 쉽게 접근하고 처리할 수 있어 유용함.
  • 고정된 크기: 배열의 크기는 초기화 시점에 고정되며, 이후에는 변경 불가.
  • 동일한 타입만 저장: 배열은 동일한 타입의 데이터만 저장할 수 있어, 다양한 타입을 한 배열에 저장하기 어려움.
  • 삽입과 삭제의 비효율성: 배열 중간에 요소를 삽입하거나 삭제하는 경우, 요소들을 이동해야하므로 성능이 저하될 수 있음.

 

System.Array: C#에서 모든 배열의 기본 클래스, 배열을 관리하고 조작할 수 있는 여러 메소드와 속성을 제공하는 클래스.

 

특징

  • 모든 배열의 기본 클래스: System.Array는 모든 배열이 상속하는 클래스. 배열 생성할때마다 이 클래스의 기본 메소드와 속성 사용 가능.
  • 배열 조작 기능 제공: 정렬, 검색, 복사, 초기화 등의 기능을 제공함.
  • 정적 메소드로 사용: 대부분의 기능은 System.Array 클래스의정적 메소드를 통해 바로 호출할 수 있으며, 특정 배열 인스턴스를 필요로 하지 않음.

속성

1.Length 속성: 배열의 총 길이를 반환함.

int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine(numbers.Length); // 출력: 5

2.GetLength 메소드: 특정 차원의 길이 반환. 다차원 배열에서 각 차원의 길이를 구할 때 유용함.

int[,] matrix = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
Console.WriteLine(matrix.GetLength(0)); // 출력: 3 (행의 개수)
Console.WriteLine(matrix.GetLength(1)); // 출력: 2 (열의 개수)

3.Clear 메소드: 배열의 모든 요소를 기본값으로 초기화함.

int[] numbers = { 1, 2, 3, 4, 5 };
Array.Clear(numbers, 0, numbers.Length); // 모든 요소를 0으로 초기화

4.Copy 메소드: 하나의 배열을 다른 배열에 복사함.

int[] source = { 1, 2, 3 };
int[] destination = new int[3];
Array.Copy(source, destination, source.Length);

foreach (var item in destination)
{
    Console.WriteLine(item); // 출력: 1, 2, 3
}

5.Sort 메소드: 배열의 요소를 오름차순으로 정렬함.

int[] numbers = { 3, 1, 4, 1, 5 };
Array.Sort(numbers);

foreach (var number in numbers)
{
    Console.WriteLine(number); // 출력: 1, 1, 3, 4, 5
}

6.Reverse 메소드: 배열의 요소를 역순으로 정렬함.

int[] numbers = { 1, 2, 3, 4, 5 };
Array.Reverse(numbers);

foreach (var number in numbers)
{
    Console.WriteLine(number); // 출력: 5, 4, 3, 2, 1
}

7.IndexOf 메소드: 특정 요소의 인덕스를 반환함. 요소가 없으면 -1을 반환함.

int[] numbers = { 1, 2, 3, 4, 5 };
int index = Array.IndexOf(numbers, 3);
Console.WriteLine(index); // 출력: 2

 

장점과 한계

  • 다양한 배열 조작 기능: 배열의 정렬, 검색, 복사, 초기화 등 다양한 기능을 제공해 배열을 쉽게 다룰 수 있음.
  • 다차원 배열 지원: 단일 배열뿐만 아니라 다차원 배열에 대해서도 다양한 조작이 가능함.
  • 정적 메소드 사용의 편리함: 대부분의 메소드가 정적 메소드이므로 객체 생성 없이도 배열을 처리할 수 있음.
  • 크기 변경 불가: System.Array는 제네릭 컬렉션이 아니기 때문에, 컬렉션과 달리 타입 안전성이 제한될 수 있음.
  • 제너릭 미지원: System.Array는 제네릭 컬렉션이 아니기 때문에, 컬렉션과 달린 타입 안전성이 제한될 수 있음.

 

컬렉션(Collection): 데이터를 그룹으로 묶어 관리하고 조작을 할 수 있는 자료 구조.동적 크기 조절이 가능하여, 배열과 달린 크기를 고정하지 않고 데이터 추가 및 삭제가 가능함.

 

특징

  • 동적 크기 조절: 컬렉션은 필요에 따라 자동으로 크기를 조정하여 데이터를 저장할 수 있음.
  • 다양한 자료 구조 지원: 리스트, 큐, 스택, 딕셔너리 등 다양한 자료 구조를 제공하여, 데이터의 삽입, 삭제, 검샥, 정렬 등을 용이하게 함.
  • 제네릭과 비 제네릭 지원: 제네릭 컬랙션을 사용하면 데이터 타입을 미리 지정할 수 있어, 타입 안전성과 성능을 높일 수 있음.

종류

1.제네릭 컬렉션(System.Collection.Generic): 특정 데이터 타입을 지정할 수 있는 컬렉션으로, 컴파일 시점에 타입이 고정되므로 타입 안전성을 제공하고 성능이 우수함. 형 변환이 필요없고, 컬렉션 내의 데이터 타입이 일관되게 유지됨.

  • List<T>: 가변 크기의 리스트. 데이터 추가, 삭제가 가능하며 인덱스를 통해 접근 할 수 있음.
List<int> numbers = new List<int> { 1, 2, 3 };
numbers.Add(4); // 요소 추가
numbers.Remove(2); // 요소 제거
  • Dictionary<TKey, TValue>: 키와 값이 쌍으로 데이터를 저장하며, 키를 통해 값에 접근할 수 있음.
Dictionary<string, int> ages = new Dictionary<string, int> { { "Alice", 30 }, { "Bob", 25 } };
Console.WriteLine(ages["Alice"]); // 출력: 30
  • HashSet<T>: 중복 없는 요소를 저장하는 집합 컬랙션. 요소의 중복을 허용하지 않음.
HashSet<int> uniqueNumbers = new HashSet<int> { 1, 2, 3, 3 };
  • Queue<T>:선입선출(FIFO)방식으로 요소를 처리하는 큐 자리 구조임.
Queue<string> queue = new Queue<string>();
queue.Enqueue("First");
queue.Enqueue("Second");
queue.Dequeue(); // "First"를 제거
  • Stack<T>: 후입선출(LIFO)방식으로 요소를 처리하는 스택 자료 구조임.
Stack<string> stack = new Stack<string>();
stack.Push("First");
stack.Push("Second");
stack.Pop(); // "Second"를 제거

 

2.비제네릭 컬렉션(System.Collections): 객체 형식으로 데이터 저장. 데이터 접근 시 형 변환이 필요하며, 타입 안전성이 떨어짐.

  • ArrayList: 크기가 가변적인 배열,다양한 타입의 데이터를 저장할 수 있음
ArrayList list = new ArrayList { 1, "Hello", true };
list.Add(3.14);
  • Hashtable: 키-값 쌍으로 데이터를 저장하는 컬렉션으로, 제네릴 딕셔너리와 유사하지만 타입 안전성을 제공하지 않음.
Hashtable table = new Hashtable();
table["Alice"] = 30;
table["Bob"] = 25;
  • QueueStack: 비제네릭 컬렉션으로, Queue<T>Stack<T>의 제네릭 버전이 없던 시절에 주로 사용됨.

 

인덱서(Indexer): 클래스나 구조체가 배열처럼 인덱스를 통해 개별 요소에 접근할 수 있게 해주는 특수한 속성. 일반 속성과 비슷하지만, 매개변수를 받아 특정 위치의 데이터를 반환하거나 설정할 수 있다는 점에서 차이가 있음.

 

인덱스 구조: this 키워드와 대활호([])를 사용하여 정의. getset 접근자를 포함할 수 있음

public class SampleCollection
{
    private int[] numbers = new int[10]; // 내부 배열

    // 인덱서 정의
    public int this[int index]
    {
        get { return numbers[index]; } // 인덱스를 통해 값 읽기
        set { numbers[index] = value; } // 인덱스를 통해 값 설정
    }
}
//사용예시
SampleCollection collection = new SampleCollection();

// 인덱스를 통해 데이터 설정
collection[0] = 10;
collection[1] = 20;

// 인덱스를 통해 데이터 읽기
Console.WriteLine(collection[0]); // 출력: 10
Console.WriteLine(collection[1]); // 출력: 20

 

장점

  • 배열처럼 객체를 사용 가능: 객체를 배열처럼 다룰 수 있어 코드가 직관적이고 간결해짐.
  • 데이터 캡슐화: 내부 데이터를 외부에서 직접 접근하지 않고 인덕스를 통해 안전하게 접근할 수 있음.
  • 유연한 데이터 접근: 객체에 포함된 데이터를 특정 조건에 따라 유연하게 접근하고 수정할 수 있음.

인덱서와 속성의 차이점

  • 인덱서는 매개변수를 통해 데이터를 관리할 수 있어 다수의 데이터를 다룰 때 유리함.
  • 속성은 특정 필드에 대한 접근을 제어하여, 보통 단일 값을 반환하거나 설정하는데 사용됨.
  • 인덱서는 이름이 없고 this 키워드를 사용하지만, 속성은 이름을 가지며 개별적으로 정의됨.
public class Student
{
    private Dictionary<string, int> scores = new Dictionary<string, int>();

    // 인덱서: 과목 이름을 통해 점수를 설정하고 가져온다.
    public int this[string subject]
    {
        get { return scores.ContainsKey(subject) ? scores[subject] : 0; }
        set { scores[subject] = value; }
    }

    // 속성: 학생의 이름을 설정하고 가져온다.
    public string Name { get; set; }
}
//사용예시
Student student = new Student();
student.Name = "Alice";  // 속성을 통해 이름 설정
student["Math"] = 95;    // 인덱서를 통해 점수 설정

Console.WriteLine($"Name: {student.Name}, Math Score: {student["Math"]}");
// 출력: Name: Alice, Math Score: 95

 

 

foreach 문: 컬렉션 또는 배열의 모든 요소를 순회하면서 각 요소에 접근할 수 있게 해주는 반복문. 인덱스나 조건을 사용하지 않고, 컬렉션의 처음부터 끝까지 모든 요소를 자동으로 순회하기 때문에 코드가 간결하고 가독성이 좋음. 배열, 리스트, 딕셔너리등 다양한 컬렉션과 함께 사용할 수 있으며, 내부적으로 컬렉션의 각 요소에 대해 IEnumerator 인터페이스를 사용하여 반복을 수행함.

 

foreach 문의 구조

foreach (var item in collection)
{
    // 컬렉션의 각 요소에 대해 실행할 코드
}

 

  • var item: 컬렉션의 각 요소가 저장될 변수. var를 사용하면 컴파일러가 자동으로 요소의 타입을 추론하며, 요소의 타입을 명시적으로 지정할 수도 있음.
  • in collection: 반복할 대상 컬렉션 또는 배열.
  • 반복문 블록: 컬렉션의 각 요소에 대해 실행할 코드를 정의.
int[] numbers = { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
    Console.WriteLine(number); // 각 요소를 출력
}

 

foreach 문의 제한 사항

  • 요소 수정 불가: foreach 문에서는 컬레션의 요소를 수정할 수 없음. 수정이 필요한 경우 for문 사용.
  • 모든 요소 순회: foreach 문은 걸렉션의 모든 요소를 순회하므로, 특정 조건에 따라 중간에 반복을 종료하거나 요소를 건너뛰기 어려움.
  • 컬렉션 수정 제한: foreach 문을 사용하는 동안 컬렉션의 크기를 변경(요소 추가/삭제)하면 오류가 발생함.

 

 

'2024-2 > C#' 카테고리의 다른 글

10.예외 처리하기  (0) 2024.11.10
09.일반화 프로그래밍  (0) 2024.11.10
07.프로퍼티  (0) 2024.11.10
06.인터페이스와 추상 클래스  (1) 2024.11.09
05.클래스  (2) 2024.11.09

+ Recent posts