25.09.28 개발일지 / C# 2(2) (Chapter09, Chapter10)

2025. 11. 11. 10:45·LMS 7/개발일지

Chapte09. 프로퍼티

더보기

1. 프로퍼티

> 프로퍼티란 기존 클래스에서 은닉된 멤버들에 대한 접근을 허용하는 메서드를(Get/Set) 보다 편리하게 사용할 수 있도록 만들어주는 도구임

1) 기본문법

class 클래스{
    데이터형 필드;
    접근한정자 데이터형 프로퍼티{
        get{
            return 필드;
        }
        set{
            필드 = value; // value는 프로퍼티 set 접근자의 매개변수로 간주됨
        }
    }
}
class MyClass{
    private int myField;
    public int MyField{
        get{
            return myField;
        }
        set{
            myField = value;
        }
    }
}

 

1.1) 사용법

Myclass obj = new MyClass();
obj.MyField = 3; // set
Console.WriteLine(obj.MyField); // get

+) set을 생략하고, get만 정의하면 읽기 전용 프로퍼티가 됨.

​

2) 자동 구현 프로퍼티

class MyClass{
    private string name;
    private string phoneNumber;

    public string Name{
        get{
            return name;
        }
        set{
            name = value;
        }
    }
    public string phoneNumber{
        get{
            return phoneNumber;
        }
        set{
            phoneNumber = value;
        }
    }
}

▲ 위의 프로퍼티를 보면 get은 단순히 필드를 반환하고, set은 받은 값을 필드에 적용시키는 역할만 한다. 이 경우 더 간소화 시키기 위해 자동구현 프로퍼티를 사용함

class MyClass{
    public string Name{get; set;}
    public string PhoneNumber{get; set;}
} // 자동구현
class MyClass{
    public string Name{get; set;} = "Unknown"
    public string PhoneNumber{get; set;} = "000-0000"
} // 자동구현과 동시에 초기화
MyClass obj = new MyClass();
obj.Name = "이명진"
obj.PhoneNumber = "123-4567"

> 매우 간단해진 걸 볼 수 있다.

3) 프로퍼티와 생성자

> 객체를 생성할 때 프로퍼티를 이용하여 초기화할 수 있다.

> 위의 자동구현과 동시에 초기화와의 차이점을 보면 기초 값을 프로퍼티 작성과 동시에 넣어주는 것이라 이는 프로퍼티를 생성과 동시에 초기화하는 것과 명백히 다르다.

클래스 객체 = new 클래스()
    {
        프로퍼티1 = 값,
        프로퍼티2 = 값,
        프로퍼티3 = 값
    };
MyClass obj = new MyClass();
    {
        Name = "이명진",
        PhoneNumber = "000-0000"
    };

 

4) 초기화 전용 자동 구현 프로퍼티(set -> init)

> get만 선언하는 읽기 전용 프로퍼티를 생성 당시에만 초기화할 수 있도록 하고, 이후에는 변경할 수 없도록 조절하는 프로퍼티다

> 구체적인 예로는 생년월일이 있다. 이유는 생년월일은 값을 필요로 하지만 구조적으로 변경될 수 없기 때문임(태어난 날을 바꿀 수는 없으므로).

class MyClass{
    public string Name{get; set;} // 기존 자동구현 프로퍼티
    public DateTime Birthday{get; init;} // 초기화 및 읽기 전용 자동구현 프로퍼티
}
MyClass obj = new MyClass();
    {
        Name = "이명진"
        Birthday = new DateTime(1998, 8, 6)
    };

> 프로퍼티를 이용한 생성자 초기화

> 이후 obj.Name을 통해 값을 변경할 때는 아무 문제가 없지만, obj.Birthday를 통해 값을 변경할 때는 컴파일 에러가 발생

> 이유는 Birthday 프로퍼티는 init 키워드를 통해 생성 당시에만 값을 초기화할 수 있고, 이후는 불가능하기 때문이다.

 

5) 초기화 강제(required)

> required 키워드는 초기화가 반드시 필요한 프로퍼티를 초기화할 수 있도록 강제한다

> 초기화를 하지 않으면 컴파일 에러를 발생시킨다.

class MyClass{
    public required string Name{get; set;}
    public required DateTime Birthday{get; init;}
}

 

6) 불변 객체(record)

> 불변 객체란 내부 필드를 변경할 수 없는 객체를 말함

> 불변 객체는 보통 불변 객체 일부를 수정한 새로운 객체를 만들어 불변 객체와 비교를 하기위해 사용됨

record MyClass{
    public string Name {get; set;}
    public DateTime Birthday {get; init;}
}
MyClass obj = new MyClass()
    {
        Name = "이명진",
        Birthday = new DateTime(1998, 8, 6)
    };

> 불변 객체 생성

> 보다시피 기존 클래스를 통한 객체 생성과정과 똑같다

> 하지만 내부 값은 더 이상 변경할 수 없음

 

6.1) 레코드 복사(with)

> with 키워드는 레코드 형식을 위한 복사 키워드임

MyClass obj = new MyClass() {Name = "이명진", Birthday = new DateTime(1998, 8, 6)};
MyClass obj2 = obj with {Birthday = new DateTime(1998, 9, 7)};

▲ with는 obj를 그대로 복사하되, Birthday 부분만 위처럼 변경하여 복사함.

 

6.2) 레코드 객체 비교(Equals())

> Eqauls 메서드는 레코드의 내용을 비교한다.

MyClass obj = new MyClass() {Name = "이명진", Birthday = new DateTime(1998, 8, 6)};
MyClass obj2 = new MyClass() {Name = "이명진", Birthday = new DateTime(1998, 8, 6)};
Console.WriteLine(obj.Equals(obj2)); // True

 

※ 주의

record가 아닌 class로 정의한 Equals 메서드는 참조 동일성을 비교한다.

class MyClass{
    public required string Name{get; set;}
    public required DateTime Birthday{get; init;}
}
MyClass obj = new MyClass() {Name = "이명진", Birthday = new DateTime(1998, 8, 6)};
MyClass obj2 = new MyClass() {Name = "이명진", Birthday = new DateTime(1998, 8, 6)};
Console.WriteLine(obj.Equals(obj2)); // False

> 내용은 같지만, obj가 참조하고 있는 곳과 obj2가 참조하고 있는 곳은 명백히 다르기 때문임.

 

2. 인터페이스 / 추상클래스의 프로퍼티

1) 인터페이스

> 인터페이스도 프로퍼티를 가질 수 있다

> 하지만 프로퍼티의 구현은 가질 수 없다

> 상속하는 파생 클래스는 프로퍼티의 구현을 강제받는다

interface IBirthday
{
    public string Name{get; set;}
    public DateTime Birthday{get; init;}
}
class MyClass : IBirthday
{
    private string name;

    public string Name{ // 직접구현
        get{return name;}
        set{name = value;}
    }
    public DateTime Birthday{get; init;} // 자동구현
}

▲ 위 처럼 인터페이스는 프로퍼티를 정의만할 뿐 구현할 수 없어 파생클래스스에서 프로퍼티를 구현하는데, 이 경우 직접구현 뿐만 아니라 자동구현도 할 수 있다.

​

2) 추상 클래스

> 추상 클래스는 인터페이스처럼 프로퍼티를 가지고, 파생 클래스들에게 강제한다.

> 다만 구현부도 가질 수 있다는 점에서 차이가 있다.(=>abstract)

abstract class Birthday{
    public string Name{get; set;} // 구현을 가진 프로퍼티(자동구현)
    abstract public DateTime Birthday{get; init;} // 구현이 없는 프로퍼티
}
class MyClass : ABirthday{
    public override DateTime Birthday(get; init;) // 추상 멤버 뿐 아니라 추상 프로퍼티 또한 override, 자동구현 사용
}

> 이전 추상 클래스를 상속했을 때 구현부는 무조건 override를 했던 것처럼 프로퍼티 또한 override 하여 재정의 해줘야 한다.

> 이미 추상 클래스에서 구현부를 가진 프로퍼티는 바로 사용할 수 있고, 구현부가 없는 프로퍼티는 따로 재정의해줘야 사용할 수 있다.


Chapter10. 배열과 컬렉션 그리고 인덱서

더보기

1. ^

> ^는 배열을 사용할 때 마지막 인덱스부터 사용할 수 있도록 해주는 키워드

1) 기본문법

^1
^2
^3
...

> ^1은 배열의 제일 마지막 요소를 나타냄

> 예를 들어 int[] num = new int[5] 라고 가정했을 때 ^1은 num[4]를 나타낸다(마지막 요소)

2) 사용법

System.Index last = ^1; // System.Index 형의 객체에 담는 경우
num[last] = 10; // num[4] = 10; 과 같다

num[^1] = 10; // 바로 쓰는 경우, num[4] = 10; 과 같다

2. 배열 초기화 방법

string[] arr = new string[2] {"안녕", "Hello"};
string[] arr2 = new string[] {"안녕", "Hello"};
string[] arr3 = {"안녕", "Hello"};

3. System.Array

> 배열들의 클래스

> int[] 도 정확히 말하면 System.Int32[]이고, System.Array를 상속한 클래스임

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

1) 정적(static) 메서드

- Sort() : 정렬

Array.Sort(nums); // 1, 2, 3, 4, 5

- Clear() : 요소 초기화

Array.Clear(nums, 0, nums.Length); // 0, 0, 0, 0, 0

- IndexOf() : 인덱스 반환

Array.IndexOf(nums, 4); // 2

- BinarySearch<T>() : 인덱스 반환(이진탐색)

Array.BinarySearch<int>(nums, 3); // 4

- TrueForAll<T>() : 모든 요소가 조건에 부합하는지(True, False)

private static bool Check(int nums){
    return nums > 1;
}
Array.TrueForAll<int>(nums, Check); // False

- Resize<T>() : 크기 재조정

Array.Resize<int>(ref nums, 10); // 1, 5, 4, 2, 3, 0, 0, 0, 0, 0
// nums를 ref(참조)로 전달하는 이유는 배열 안 변수를 변경하기 위함

- ForEach<T>() : 모든 요소에 동일한 작업 부여

- Copy<T>() : 배열 일부를 다른 배열로 복사

int[] sliced = new int[4];
Array.Copy(nums, 0, Sliced, 0, 4); // 1, 5, 4, 2

 

2) 객체 메서드

- GetLength() : 지정한 차원의 길이를 반환

nums.GetLegnth(0); // 5

 

3) 프로퍼티

- Length : 배열의 길이 반환

nums.Length; // 5

- Rank : 배열의 차원 반환

nums.Rank // 1

 

4. 배열 분할

1) System.Range와 .. 키워드

> .. 키워드를 사용하여 System.Range형 객체에 저장하여 사용할 수 있다.

System.Range r1 = 0..3; // 0번째부터 2번째까지
int[] sliced = nums[r1];

2) 다양한 형태

..3 // 0번째부터 2번째까지
1.. // 1번째부터 마지막까지
.. // 0번째부터 마지막까지
..^0 // 0번째부터 마지막까지

 

5. 가변 배열

> 배열을 요소로 하는 배열

1) 기본문법

데이터형[][]배열명 = new 데이터형[가변배열수][];
int[][] jagged = new int[3][];

2) 사용법

jagged[0] = new int[5] {1, 2, 3, 4, 5};
jagged[1] = new int[] {1, 2, 3, 4};
jagged[2] = new int[] {1, 2};

 

6. 컬렉션

> 컬렉션이란 같은 성격을 띤 데이터 모음을 담는 자료구조로써 우리가 사용하던 배열(System.Array 클래스)도 컬렉션의 일종이다.

1) ArrayList(리스트)

ArrayList list = new ArrayList();

▲ 생성

list.Add(1);
list.Add(2);
list.Add(3);
// 1, 2, 3

▲ 메서드 Add(), 마지막 요소에 새 요소를 추가

list.RemoveAt(1); // 2 제거 // 1, 3

▲ 메서드 RemoveAt(), 특정 인덱스 요소를 제거

list.Insert(0, 100); // 100을 0번째 인덱스에 삽입 // 100, 1, 3

▲ 메서드 Insert(), 특정 인덱스에 요소를 삽입

 

2) Queue(큐)

> 요소를 추가할 때는 마지막 인덱스에, 꺼낼 때(사용할 때)는 첫 인덱스로 사용하는 자료구조

Queeu que = new Queue();

que.Enqueue(1); // 추가할 때는 Enqueue를 사용
que.Enqueue(2);
que.Enqueue(3);
// 1, 2, 3

int a = que.Dequeue(); // 사용할 때는 Dequeue를 사용, 1
int b = que.Dequeue(); // 2
int c = que.Dequeue(); // 3

 

3) Stack(스택)

> Queue와 같은 점은 추가할 때는 마지막 인덱스이지만 꺼낼 때도 마지막 인덱스로 사용한다는 점에서 차이가 있다.

Stack stack = new Stack();

stack.Push(1); // 추가할 때는 Push를 사용
stack.Push(2);
stack.Push(3);
// 1, 2, 3

int a = (int)stack.Pop(); // 사용할 때는 Pop을 사용, 3
int b = (int)stack.Pop(); // 2
int c = (int)stack.Pop(); // 1

 

4) Hashtable

> 키(key)와 값(value)의 쌍으로 이루어진 자료구조임

Hashtable ht = new Hashtable();

ht["book"] = "책"; // 저장할 때는 배열의 인덱스를 사용하는 것처럼 key 값을 사용
ht["cook"] = "요리사";

Console.WriteLine(ht["book"]) // 사용할 때도 배열의 인덱스처럼 사용한다
Console.WriteLine(ht["cook"])

 

5) 컬렉션 초기화(ArrayList, Stack, Queue)

int[] arr = {1, 2, 3}; // 배열 생성

ArrayList list = new ArrayList(arr); // 1, 2, 3
Stack stack = new Stack(arr); // 1, 2, 3 // 다만 사용할 때는 3, 2, 1(후입선출)
Queue queue = new Queue(arr); // 1, 2, 3

▲ 배열 객체를 매개변수로 넘긴다

ArrayList list = new ArrayList() {1, 2, 3};

▲ ArrayList만 배열의 도움없이 초기화가 가능하다(컬렉션 초기자)

 

5.1) 컬렉션 초기화(Hashtable)

Hashtable ht = new Hashtable()
{
    {"첫번째", 1},
    {"두번째", 2},
    {"세번째", 3}
};

▲ ArrayList만 사용했던 컬렉션 초기자를 사용

Hashtable ht = new Hashtable()
{
    ["첫번째"] = 1,
    ["두번째"] = 2,
    ["세번째"] = 3
};

▲ 딕셔너리 초기자를 사용

 

7. 인덱서(Indexer)

> 인덱서란 인덱스를 사용하여 객체 내 배열이나 배열리스트(ArrayList)등과 같은 컬렉션에 접근하게 해주는 프로퍼티이다

1) 기본문법

한정자 인덱서형 this[형 인덱스명]
{
    get{}
    set{}
}

 

2) 사용법

class MyClass{
    private int[] arr = new int[5];
    public int this[int index] {
        get{ return data[index]; }
        set{ data[index] = value; }
    }
}

MyClass obj = new MyClass();
obj[0] = 0; // 사실상 data[0] = 0; 과 같음
obj[1] = 1; // 사실상 data[1] = 1; 과 같음

 

8. IEnumerable

> 위에 있는 인덱서를 사용하면 마치 객체를 배열처럼 사용할 수 있었다.

> 이는 foreach문 활용을 극대화할 수 있다는 장점을 가진다.

> 하지만 foreach문은 IEnumerable이라는 인터페이스 형식을 가지고 있어야만 사용할 수 있다.

 

1) yield

> yield 키워드는 IEnumerator 인터페이스를 구현한 클래스를 생성해준다.

> 따라서 IEnumerable을 상속하지 않아도 yield return 문을 통해 foreach를 사용 가능하다.

using System;
using System.Collections;

namespace Yield{
    class MyEnumerator{ // IEnumerable을 상속하지 않음
        int[] numbers = {1, 2, 3, 4};
        
        // yield return이 들어가는 메서드는 IEnumerator 클래스가 자동 생성됨
        public IEnumerator GetEnumerator(){ 
            yield return numbers[0];
            yield return numbers[1];
            yield return numbers[2];
            yield break;
            yield return numbers[3];
        }
    }
}

class MainApp{
    static void Main(string[] args){
        var obj = new MyEnumerator();
        foreach (int i in obj) Console.WriteLine(i);
    }
}

 

2) 직접 구현

> 직접 구현은 거의 쓰지 않는다고 함

class MyNums : IEnumerable {
    int[] data = { 1, 2, 3 };

    public IEnumerator GetEnumerator() {
        // 배열과 같은 컬렉션들은 이미 IEnumerable을 구현하고 있어, 내부의 GetEnumerator를 사용 가능하다.
        return data.GetEnumerator();
    }
}

▲ IEnumerable만 상속하여 강제하는 메서드인 GetEnumerator을 구현

class MyNums : IEnumerable, IEnumerator {
    int[] data = { 1, 2, 3 };
    int position = -1;

    public IEnumerator GetEnumerator() {
        return this;  // 자기 자신을 반환
    }

    public bool MoveNext() {
        position++;
        return (position < data.Length);
    }

    public void Reset() {
        position = -1;
    }

    public object Current {
        get { return data[position]; }
    }
}

▲ IEnumerable, IEnumerator를 모두 상속하여 강제하는 메서드인 GetEnumerator, MoveNext, Reset과 프로퍼티 Current를 구현

 

'LMS 7 > 개발일지' 카테고리의 다른 글

25.09.29 개발일지 / C# 3 (Chapter13)  (0) 2025.11.11
25.09.29 개발일지 / C# 2(3) (Chapter11, Chapter12)  (0) 2025.11.11
25.09.27 개발일지 / C# 2(1) (Chapter07, Chapter08)  (0) 2025.11.11
25.09.26 개발일지 / C# 1(1) (Chapter02~Chapter03)  (0) 2025.11.11
25.09.25 개발일지  (0) 2025.11.04
'LMS 7/개발일지' 카테고리의 다른 글
  • 25.09.29 개발일지 / C# 3 (Chapter13)
  • 25.09.29 개발일지 / C# 2(3) (Chapter11, Chapter12)
  • 25.09.27 개발일지 / C# 2(1) (Chapter07, Chapter08)
  • 25.09.26 개발일지 / C# 1(1) (Chapter02~Chapter03)
m_Dev
m_Dev
  • m_Dev
    m_Dev
    m_Dev
  • 전체
    오늘
    어제
    • 분류 전체보기
      • MAIN STUDY
        • 정보보안
        • 빅데이터
        • 정보처리
        • 컴퓨터 구조
        • 기타
      • JOB
        • Study
        • Project
      • LMS 7
        • 개발일지
      • FRAMEWORK
        • Qt
        • MFC
        • Winform
        • WPF
        • MAUI
      • NETWORK
        • Study
        • Assignment
      • PYTHON
        • Set
        • Study
        • Assignment
        • Project
      • C
        • Set
        • Study
        • Assignment
        • Project
      • C++
        • Set
        • Study
        • Assignment
        • Project
      • C#
        • Set
        • Study
        • Assignment
        • Project
      • DATABASE
        • MySQL
        • SQLite
      • IDE
        • VisualStudioCode
        • VisualStudio
        • Pycharm
        • Colab
      • 기타
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
m_Dev
25.09.28 개발일지 / C# 2(2) (Chapter09, Chapter10)
상단으로

티스토리툴바