10.8 C#

류운형
∙∙조회 7

26.10.08 기록

C# 필드와 Static

필드(field) = 클래스 안에 데이터를 담는 자리.
선언하는 방법 자체는 변수와 다르지 않지만, 클래스 안에 놓이면서 생기는 물음이 있다.

물음답
이 필드를 클래스 밖에서 건드리게 둘 것인가접근 모디파이어 (public · private)
객체마다 따로 가질 값인가, 클래스 전체에 하나뿐인 값인가static
한번 정해진 뒤에도 바뀔 수 있는 값인가readonly
csharp
public static readonly int MaxLevel = 99;

// public   → 누가 쓸 수 있는가
// static   → 누구의 것인가
// readonly → 바꿀 수 있는가

필드와 지역변수

같은 int선언이라도 놓이는 위치에 따라 성격이 갈림

csharp
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 == false
  • char == '\0'(코드 값이 0인 널 문자)
  • string, 배열, 클래스 등 참조 타입 == null

기본 값을 사용하지 않을 거라면 선언과 동시에 값을 줌. 이를 필드 이니셜라이저라고함.

필드 이니셜라이저는 객체를 만들 때 마다 실행됨.

csharp
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는 한 개의 값만 가지고 있는데. 위 코드를 실행하게 되면..

csharp
이름없음 / HP 100 / Lv.1
이름없음 / HP 100 / Lv.1

이와 같이 같은 값이 두 개가 나온다. 하지만 이는 하나의int값을 나눠가지는 것이 아닌. Player라는 객체를 만들 때마다 실행되는 것이다.


접근 모디파이어

열 것과 닫을 것

모디파이어는 2개가 있다. public , private 이 두 개는 클래스 밖에서도 해당 필드에 닿을 수 있는 지를 결정 짓는 모디파이어 이다.

csharp
Account a = new Account();
a.balance = 999999;

class Account
{
    private int balance = 5000;
}

private필드를 밖에서 건드리면 컴파일 오류. 또한, public 과 private를 둘다 적지 않을 경우 기본 값으로 private가 적용됨.

static

객체마다 따로인 것

클래스에 하나뿐인 것. 필드 앞에 static을 붙이면 객체가 아니라 클래스에 붙음.

csharp
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 을 사용할 경우

상황

판단

값이 객체마다 달라짐 (이름, 체력)

인스턴스

값이 클래스 전체에 하나임 (생성 개수, 설정값)

static

넘겨받은 인수만으로 결과가 정해짐

static 메서드

객체의 필드를 읽거나 바꿔야 함

인스턴스 메서드

객체를 만들 일이 전혀 없고 기능만 모음

static class

정말로 클래스 전체에 하나뿐인 값일 때만 쓸 것


나머지는 집에서 다시 보니까 다시 이해가 안돼서 다음에 다시 정리 예정.

최근 수업에서 수업을 들을 때는 내용을 좀 이해 하다가. 문제 코드를 작성할 때부터 막혀버리니 답답하고 이렇게 못해도 되는 건가 싶은 생각도 든다. ㅎ

근데 나중에 다시 보면 수업에서 들었던 내용도 잘 기억하지 못해서 오늘 보강 수업 때 교무과장님께 질문을 하나 드렸다.

"어느 정도 시간이 지나야 코딩을 잘하는지 못하는지 판단 하는 게 맞을까요?"

과장님께서는 직접 경험하셨던 혈이 뚫리는? 시점이 있다고 말씀해주셨다.

과장님 말씀 듣고 맘 다잡고 열심히 해서 혈 뚫리길 기.도.!