생성자(Constructor)
생성자는 클래스가 인스턴스화 될 때 자동으로 호출되는 특수한 메서드다.
객체가 만들어지는 순간 필드 초기화, 리소스 확보, 기본값 설정 등을 처리한다.
이름은 클래스명과 동일하며 반환형을 명시하지 않는 특징이 있다.
void 조차 적지 않는다.
public [클래스명] (원하는매개변수)
{
// 생성과 동시에 실행이 되었으면 하는 코드
}
이렇게 사용하면 된다.
이 생성자는 new 키워드와 함께 인스턴스 생성시 자동 호출된다.
생성자를 따로 작성하지 않으면 C#은 매개변수가 없는 기본 생성자를 제공한다.
Visual Studio 에서는 ctor을 치면 자동완성해주는 기능이 있다.
Visual Studio Code에서도 되는데 C# 익스텐션이 필요한지 어떤지는 잘 모르겠다. 안되면 익스텐션을 설치해보길...
또한 오버로딩이 되기 때문에 입력되는 매개변수에 따라 다르게 작동시킬 수 있다.
오버로딩은 같은 이름의 메서드를 매개변수의 개수, 타입, 순서에 따라 다르게 정의했을 때, 호출 시점에 전달되는 인자의 형태에 맞춰 알맞은 메서드가 선택되는 편리한 기능 정도로 알아두면 된다.
class Pet
{
// 자동구현 프로퍼티
public string Name { get; set; }
public int Level { get; set; }
public string Skill { get; set; }
public Pet()
{
Console.WriteLine("; ㅁ ;");
}
public Pet(string petName)
{
Name = petName;
Console.WriteLine("your pet Name is " + petName);
}
public Pet(string petName, int initLvl)
{
Name = petName;
Level = initLvl;
Console.WriteLine($"{petName}, your pet Level is " + initLvl);
}
};
위에서부터 아무것도 매개변수를 입력하지 않았을 때,
문자열 하나만 입력했을 때,
문자열과 숫자를 입력했을 때의 경우에 맞게 출력된다.
Pet pet1 = new Pet();
// ;ㅁ; 출력
Pet pet2 = new Pet("Omegamon");
// your pet Name is Omegamon 출력
Pet pet1 = new Pet("Omegamon", 99);
// Omegamon, your pet Level is 99 출력
그리고 위 코드의 주석을 보면 자동구현 프로퍼티라고 돼있다.
Auto-Implemented Property 라고 하는데, 필드를 따로 선언하지 않고 프로퍼티만 정의하는 방식이다.
이 경우 컴파일러가 자동으로 백킹 필드<backing field>(힙 영역)를 생성하주는 문법으로, 기존에는 내부적으로 관리할 변수를 private으로 두고, 프로퍼티를 따로 또 구현해야했는데, 별도의 검증이나 추가 동작 없이 단순히 get, set 만 필요한 경우에 유용하게 사용할 수 있다.
디폴트 매개변수 라는 것도 있다.
말 그대로 초기값을 설정해주는 건데 필요에 따라 잘 사용하면 된다.
using System;
namespace ClassCtor
{
class Trainer
{
int level;
public int Level
{
get { return level; }
set { level = value; }
}
public string Name { get; set; }
// 디폴트 매개변수
public Trainer(int lvl, string nName = "초기이름")
{
level = lvl;
Name = nName;
}
// 이러고 int만 매개변수 넣으면 아래꺼가 수행됨
public Trainer(int lvl)
{
level = lvl;
Console.WriteLine("숫자 하나만 생성");
}
}
}
주의할 점은, 디폴트 매개변수는 뒤쪽에서부터 만들어야한다는 점과, 위 코드처럼 디폴트 매개변수가 있을때 해당 매개변수를 입력하지 않은 경우, 디폴트 매개변수가 없는 쪽의 생성자가 실행되니 주의하자.
소멸자(Destructor)
소멸자는 생성자와 반대 개념으로, 객체가 메모리에서 해제될 때 자동으로 호출되는 특수한 메서드다.
주로 리소스 정리(Dispose와 같은 역할)을 할 때 쓰이며, 생성자처럼 반환형이 없고 클래스명과 동일한 이름을 가진다.
~Trainer() 와 같은 형태로 선언하면 된다.
특징으로는 클래스에서만 정의할 수 있고, 구조체에서는 사용할 수 없다.
.NET의 가비지 컬렉터(GC)가 동작시 호출되기 때문에 호출 시점에 예상과 다른 동작을 할 수 있어 주의해야한다.
파일 입출력, 네트워크 연결 해제 등 특정 상황에서 쓰인다.
부분 클래스(Partial Class)
하나의 클래스를 여러 파일에 나눠서 정의하는 기능이다.
규모가 큰 프로젝트에서 코드 관리와 가독성을 높이기 위해 사용된다.
// Monster.cs
partial class Monster
{
public string Name { get; set; }
public int Level { get; set; }
}
// Monster2.cs
partial class Monster
{
public void Attack()
{
// 동작
}
}
위 코드 처럼 서로 다른 파일에서 partial을 통해 동일한 이름의 클래스를 만들어 줄 수 있다.
한 쪽에는 변수만, 한 쪽에는 메서드만 배치해서 정리한다거나 같은 클래스의 코드를 분업하거나 하는 등 여러 방면으로 사용될 수 있다.
분리된 클래스 끼리는 당연히 모든 내용이 공유되어 하나의 클래스 안에 있는 것과 동일하게 동작한다.
Namespace
C# 소스 파일을 생성하면 가장 상단에 namespace 라는 것이 보일거다.
이 네임스페이스는 코드간의 이름 충돌을 방지하고 논리적으로 그룹화하기 위한 공간이다.
일종의 폴더 개념으로 보면 된다.
using 키워드를 통해 특정 네임스페이스에서 데이터를 가져올 수 있는데, 실무에서는 풀네임으로 접근하는 걸 권장한다.
using Game.Creature; // 네임 스페이스에서 직접 가져오기. 권장 X
.
.
.
Creature.Monster.Gen(); // 풀 네임으로 메서드 호출하기. 권장
깊은 복사 & 얕은 복사
값 타입, 참조 타입 데이터에 대해서는 지금까지 글에서 여러번 다뤘을 것이다.
참조형 데이터는 값 자체가 아닌 그 값을 가리키고 있는 주소(참조)를 복사한다는 특성이 있었다.
- 얕은 복사 (Shallow Copy) : 참조만 복사, 두 객체가 같은 메모리를 가리킴. 한쪽 변경 시 다른 쪽도 영향 받음.
- 깊은 복사 (Deep Copy) : 새로운 메모리를 확보하고 내부 값까지 전부 복제. 서로 영향을 주지 않음.
class Pet
{
public string Name { get; set; }
}
Pet pet1 = new Pet { Name = "Omegamon" };
Pet pet2 = pet1; // 얕은 복사 (둘 다 같은 객체를 참조)
Pet pet3 = new Pet { Name = pet1.Name }; // 깊은 복사
이렇게 pet2에 pet1을 직접 넣으면 얕은 복사가 이뤄져서 같은 주소값을 가리키게 되지만
New Pet을 한 뒤, 거기에 pet1의 데이터를 넣는다 한들 새로운 데이터 공간이 만들어져서 Pet3으로 복사되기 때문에 이 경우에는 두 데이터가 이후 수정이 발생해도 서로 영향을 주지 않게 된다.
이것을 깊은 복사라고 한다.
매개변수 한정자 (Parameter Modifier)
ref / in / out 과 같은 매개변수 한정자를 붙이면 함수 호출 시 인자를 전달하는 방식이 달라진다.
ref - 이미 초기화된 변수를 참조로 전달한다. 함수 안에서 변경하면 호출한 원본 변수에도 반영된다.
void Add(ref int x) { x += 10; }
int num = 5;
Add(ref num); // num은 15가 됨
out - ref와 비슷한데 함수 안에서 반드시 초기화해야 한다. 함수가 여러 값을 반환해야 할 때 유용하다.
void Divide(int a, int b, out int quotient, out int remainder)
{
quotient = a / b;
remainder = a % b;
}
int q, r;
Divide(10, 3, out q, out r); // q=3, r=1
in - 읽기 전용 참조 전달로 함수 안에서 값을 변경할 수 없다. 대용량 구조체 등에 사용된다.
void Print(in int x)
{
Console.WriteLine(x); // 읽기 전용
x = 500; // 안됨
}
int num = 100;
Print(num);
수정하면 안되는데 수정하려 하면 컴파일 에러가 발생한다.
'C#' 카테고리의 다른 글
| C# - 메모리와 가비지 컬렉터 (GC) (0) | 2025.09.17 |
|---|---|
| C# - 클래스 실습 문제 풀이 (생성자) (0) | 2025.09.17 |
| C# - 클래스 (Class) 생성 실습 문제 풀이 (0) | 2025.09.15 |
| C# - 클래스(Class) & 객체지향 (1) | 2025.09.15 |
| 버전관리 : Git, GitHub, GitHub Desktop (0) | 2025.09.13 |