10.8 C#
26.10.08 기록
C# 필드와 Static
필드(field) = 클래스 안에 데이터를 담는 자리.
선언하는 방법 자체는 변수와 다르지 않지만, 클래스 안에 놓이면서 생기는 물음이 있다.
| 물음 | 답 |
|---|---|
| 이 필드를 클래스 밖에서 건드리게 둘 것인가 | 접근 모디파이어 (public · private) |
| 객체마다 따로 가질 값인가, 클래스 전체에 하나뿐인 값인가 | static |
| 한번 정해진 뒤에도 바뀔 수 있는 값인가 | readonly |
public static readonly int MaxLevel = 99;
// public → 누가 쓸 수 있는가
// static → 누구의 것인가
// readonly → 바꿀 수 있는가
필드와 지역변수
같은 int선언이라도 놓이는 위치에 따라 성격이 갈림
using System;
Counter c = new Counter();
c.Add();
c.Add();
c.Add();
class Counter
{
private int total; // 필드 — 객체가 살아 있는 동안 유지됨
public void Add()
{
int step = 1; // 지역 변수 — 이 메서드를 벗어나면 사라짐
total = total + step;
Console.WriteLine($"누적 {total}");
}
}
| 구분 | 선언 위치 | 유지 | 가용 범위 |
|---|---|---|---|
| 지역 변수 | 메서드 블록 안 | 메서드가 끝날 때까지 | 선언한 블록 안 |
| 필드 | 클래스 블록 바로 안 | 객체가 살아 있는 동안 | 클래스 안의 모든 메서드 |
지역 변수는 초기화 하기 전에 사용하면 컴파일 오류가 생기지만, 필드(field)는 기본 값을 가지고 있기 때문에 초기화 전에도 사용 가능.
- 정수(
int,short,long, ...) == 0 - 실수
float,double) == 0 bool== falsechar== '\0'(코드 값이 0인 널 문자)string, 배열, 클래스 등 참조 타입 ==null
기본 값을 사용하지 않을 거라면 선언과 동시에 값을 줌. 이를 필드 이니셜라이저라고함.
필드 이니셜라이저는 객체를 만들 때 마다 실행됨.
using System;
Player p1 = new Player();
Player p2 = new Player();
p1.Show();
p2.Show();
class Player
{
private string name = "이름없음";
private int health = 100;
private int level = 1;
public void Show()
{
Console.WriteLine($"{name} / HP {health} / Lv.{level}");
}
}
예시 코드에서 int는 한 개의 값만 가지고 있는데. 위 코드를 실행하게 되면..
이름없음 / HP 100 / Lv.1
이름없음 / HP 100 / Lv.1
이와 같이 같은 값이 두 개가 나온다. 하지만 이는 하나의int값을 나눠가지는 것이 아닌. Player라는 객체를 만들 때마다 실행되는 것이다.
접근 모디파이어
열 것과 닫을 것
모디파이어는 2개가 있다. public , private 이 두 개는 클래스 밖에서도 해당 필드에 닿을 수 있는 지를 결정 짓는 모디파이어 이다.
Account a = new Account();
a.balance = 999999;
class Account
{
private int balance = 5000;
}
private필드를 밖에서 건드리면 컴파일 오류. 또한, public 과 private를 둘다 적지 않을 경우 기본 값으로 private가 적용됨.
static
객체마다 따로인 것
클래스에 하나뿐인 것. 필드 앞에 static을 붙이면 객체가 아니라 클래스에 붙음.

using System;
Monster a = new Monster();
a.Name = "고블린";
Monster.SpawnCount++;
Monster b = new Monster();
b.Name = "오크";
Monster.SpawnCount++;
Monster c = new Monster();
c.Name = "슬라임";
Monster.SpawnCount++;
Console.WriteLine($"a의 이름: {a.Name}");
Console.WriteLine($"b의 이름: {b.Name}");
Console.WriteLine($"c의 이름: {c.Name}");
Console.WriteLine($"지금까지 등장한 몬스터: {Monster.SpawnCount}마리");
class Monster
{
public string Name; // 객체마다 따로
public static int SpawnCount; // 클래스에 하나
}
정적 필드는 객체 이름이 아니라 클래스 이름으로 쓴다.
인스턴스 필드 | a.Name - 객체 이름
정적 필드 | Monster.SpawnCount - 클래스 이름
객체 이름으로 정적 필드에 닿으려 하면 컴파일 오류가 남.
정적 메서드, 클래스
메서드에도 static 을 붙일 수 있음. 객체 없이 클래스 이름으로 부름
클래스 전체에 static 을 붙이면 정적 멤버만 담을 수 있고new 로 객체를 만들 수 없는 클래스가 됨.
static 을 사용할 경우
상황 | 판단 |
|---|---|
값이 객체마다 달라짐 (이름, 체력) | 인스턴스 |
값이 클래스 전체에 하나임 (생성 개수, 설정값) |
|
넘겨받은 인수만으로 결과가 정해짐 |
|
객체의 필드를 읽거나 바꿔야 함 | 인스턴스 메서드 |
객체를 만들 일이 전혀 없고 기능만 모음 |
|
정말로 클래스 전체에 하나뿐인 값일 때만 쓸 것
나머지는 집에서 다시 보니까 다시 이해가 안돼서 다음에 다시 정리 예정.
최근 수업에서 수업을 들을 때는 내용을 좀 이해 하다가. 문제 코드를 작성할 때부터 막혀버리니 답답하고 이렇게 못해도 되는 건가 싶은 생각도 든다. ㅎ
근데 나중에 다시 보면 수업에서 들었던 내용도 잘 기억하지 못해서 오늘 보강 수업 때 교무과장님께 질문을 하나 드렸다.
"어느 정도 시간이 지나야 코딩을 잘하는지 못하는지 판단 하는 게 맞을까요?"
과장님께서는 직접 경험하셨던 혈이 뚫리는? 시점이 있다고 말씀해주셨다.
과장님 말씀 듣고 맘 다잡고 열심히 해서 혈 뚫리길 기.도.!


자주 하고 자주 보면 익숙해지고, 익숙해지다 보면, 쉬워지고, 쉬워지다보면 혈이 뚫리지 않을까요?