클래스는 나만의 타입을 만들 수 있는 도구입니다. 클래스는 여러 가지 멤버(Member)로 표현됩니다. 멤버의 종류에는
아래와 같습니다.
필드
상수
프로퍼티
메소드
이벤트
연산자
인덱서
생성자
종료자
네스티드 타입
이 중에서 필드 / 상수 / 메소드 / 프로퍼티 / 생성자를 먼저 배워보겠습니다.

메소드는 함수로 클래스가 할 수 있는 행위를 정의합니다.
클래스를 만들면 보통 필드를 직접 수정한다기보다는 메소드를 호출해 데이터를 조작하는 것이 일반적입니다.
메소드는 같은 이름을 사용할 수 있습니다. 단, 이 경우 시그니처(Signature)가 달라야합니다.
이런 기능을 오버로딩(Overloading)이라고 하며, 입력된 데이터를 달리할 때나 헬퍼 함수를 정의하는데 사용할 수 있습니다.


// Foo, Foo(int a), Foo(double)이 오버로딩입니다.
// public int Foo()와 public void Foo(int b)는 오류입니다.

옛날 C언어 사용 당시에는 함수마다 이름을 서로 다르게 작명을 했어야 하는 어려움이 있었습니다. 하지만 C#은 오버로딩을 지원해서 작명에 대한 부담감을 덜어줬습니다. 단, 가독성이 있는지, 없는지에 대한 의견은 나뉘지만, 교수님께서는 오버로딩은 좋다고 생각한다는 의견을 내셨습니다.
오버로딩을 하고 싶다면 ‘매개변수’가 달라야합니다. 반환 타입이나, 접근자를 다르게 한다고 해서 오버로딩이 되지 않습니다.

클래스를 설계할 때는 사용자가 직접 데이터를 건드리지 않고, 주어진 메소드만을 활용해서 간접적으로 데이터를 조작하게끔 만드는 것이 좋습니다. 그래야 사용성이 증대되기 때문입니다.
하지만 가끔은 데이터에 직접 접근할 수 있는 메소드를 정의해야 할 때가 있습니다. 이를 Setter 및 Getter라고 합니다.


하지만 매번 설정자와 접근자를 입력하는 것은 귀찮은 일이기에 C#에서는 편리한 방법을 제공합니다. 바로 ‘Property’입니다.

// private set은 해당 클래스 내부에서만 변경이 가능합니다.
변수처럼 사용이 가능합니다.


객체의 데이터를 초기화하는 메서드입니다.

// 반환값은 따로 없습니다.
// Class와 이름이 같아야합니다.
생성자는 딱히 정의하지 않아도 상관 없는데, C#이 알아서 매개변수가 없는(Parameterless) 생성자를 만들어내기 때문입니다.


상수처럼 클래스 타입도 더 이상 수정되지 않길 원한다면 reandonly 한정자를 사용할 수 있습니다.
readonly는 필드를 정의할 때 붙일 수 있으며, 해당 필드는 생성자 안에서만 값을 할당할 수 있습니다.
생성자 범위를 벗어나면 값을 할당하지 못합니다.

인스턴스끼리는 데이터가 독립적입니다.

헌데 어떻게 이런 일이 가능할까? 여기엔 this 포인터가 있습니다. 사실 필드를 사용할 때 this가 생략되어 있습니다. this는 주소 값이 저장되어 있습니다.
인스턴스 멤버는 전부 this가 생략되어 있습니다.


this를 명시적으로 작성할 일은 없습니다.
단, 내부적으로 character1 과 character2를 나눠주는 역할을 하는 것이 this라는 것을 이해하고 있으면 됩니다.
static 한정자를 사용하면 멤버를 정적(static)으로 만들 수 있습니다.
정적 멤버가 되면 인스턴스끼리 공유하는 멤버가 됩니다.

// static이 없다면 character1 = 90, character2 = 90이어야합니다.
// 하지만 static을 사용하면 멤버를 공유하기 때문에 100 - 10 - 10 = 80이 되는 것입니다.
정적 멤버는 클래스 이름을 통해서만 접근합니다.


접근 한정자 및 매개변수를 가지지 않습니다.
오직 하나만 존재합니다.
직접적으로 호출할 수 없습니다. CLR에 의해서만 자동으로 호출됩니다.


Tip 정적 멤버에는 this라는 개념이 없습니다.
왜냐구요??
간단합니다. 정적 멤버는 인스턴스끼리 공유하기 때문입니다!
그러니 this라는 개념이 없는 것입니다.
이미 존재하는 타입에 우리의 메소드를 추가할 수 있습니다. 이를 확장 메소드라고 합니다.
확장 메소드를 이용하면 마치 원래 있던 메소드마냥 사용할 수 있습니다.
예를 들어 .NET 7에서 밖에 사용할 수 없는 Regex.Count()를 .NET 6에서 추가한다고 해보겠습니다.
백준 15881번 문제

// this 쓰지 않으면 그냥 정적 메소드입니다.
// 확장 메소드와 정적 메소드를 구분할 줄 알아야합니다.
// 여기서 this는 인스턴스 this랑 다른겁니다. 견문이 넓어지다보면 무엇이 다른지, 이해할 수 있습니다. 견문아 높아져라 얍~!
클래스 멤버에는 인덱서가 있습니다.
형식 또는 인스턴스 멤버를 명시적으로 지정하지 않고 인덱싱된 값을 설정하거나 검색할 수 있습니다.
인덱서는 접근자가 매개변수를 사용하다는 점을 제외하면 속성과 비슷합니다.
쉽게 말해 클래스의 값을 배열처럼 접근할 수 있도록 해주는 문법입니다.
인덱서를 사용하면 배열과 유사한 방식으로 개체를 인덱싱 할 수 있습니다.
접근자는 값 get을 반환합니다. 접근자는 값 set을 할당합니다.
this 키워드는 인덱서를 정의하는데 사용됩니다.
value 키워드는 접근자가 할당하는 값을 정의하는데 사용됩니다. - > set에서 사용
인덱서는 정수 값으로 인덱싱 할 필요가 없습니다. 특정 조회 매커니즘을 정의하는 방법은 사용자에게 달려 있습니다.
인덱서는 오버로드 될 수 있습니다.

한정자 : public, private, protected 등 접근 한정자를 설정합니다.
타입 : 인덱서 반환 타입을 정의합니다. - Object 타입은 지양합시다. 사용하지 않는 것이 좋습니다.
this : 현재 클래스에 대해 인덱서를 정의하고 있음을 나타냅니다.
int형 인덱스 또는 string명 : 인덱스 위치를 int형 인덱스로 접근할 것인지 또는 string 명으로 접근할 것인지 설정합니다.
