■ 개요
○ 오늘 계획
■ 클래스의 메모리
○ 클래스 정의
- 클래스 정의 자체는 데이터 메모리에 적재되는 것이 아니라, 프로그램이 실행될 때 CLR(Common Language Runtime)에 의해 관리됩니다.
- 즉, 클래스의 메타데이터는 메타데이터 영역이나 CLR의 관리 영역에 저장됩니다.
○ 객체 생성
- C#에서 객체를 생성하면, 객체의 실제 데이터(인스턴스 필드)는 힙(Heap) 메모리에 저장됩니다.
- 객체 참조는 스택(Stack) 메모리에 저장됩니다.
MyClass obj = new MyClass();
- obj는 스택 메모리에 저장된 참조(reference)입니다.
- new MyClass()로 생성된 실제 객체는 힙 메모리에 저장됩니다.
○ 값 타입
- 만약 클래스가 아니라 값 타입(Struct, Primitive Type)이라면, 그것은 스택 메모리에 저장됩니다(일반적으로 지역 변수일 경우).
- 하지만 힙 객체의 필드로 사용될 경우에는 힙 메모리에 포함됩니다.
○ 요약
- 클래스 정의: CLR의 메타데이터 관리 영역.
- 객체 데이터: 힙(Heap) 메모리.
- 객체 참조: 스택(Stack) 메모리.
■ static의 인스턴스 접근불가
○ 원인
static
메서드나 생성자에서 인스턴스 멤버에 접근할 수 없는 이유는 다음과 같은 C#의 설계 원칙과 메모리 모델 때문
○ 상세 원인 분석
- 메모리 모델과 접근의 맥락
static
멤버는 클래스 자체에 속하며, 클래스가 로드될 때 메모리에 한 번만 할당됩니다.
- 이 멤버는 인스턴스와 무관하게 동작하므로 클래스 차원에서 관리됩니다.
- 따라서 static 메서드나 필드는 어떤 특정 인스턴스에도 종속되지 않습니다.
- 인스턴스 멤버는 개별 객체(인스턴스)에 속하며, 객체가 생성될 때 힙 메모리에 각각의 데이터가 따로 할당됩니다.
- 이를 접근하려면 어떤 특정 객체의 참조를 통해야만 합니다.
- 코드 관점에서의 동작 원리
static
메서드는 클래스 로드 시점에 메모리에 존재하며, 어떤 객체가 존재하지 않아도 호출될 수 있습니다. 반면, 인스턴스 멤버는 객체가 생성되어야만 의미가 있습니다.
class MyClass
{
public int InstanceField = 10;
public static int StaticField = 20;
public static void StaticMethod()
{
// Console.WriteLine(InstanceField); // 오류 발생
Console.WriteLine(StaticField); // static 필드는 접근 가능
}
}
- 위 코드에서 StaticMethod는 InstanceField에 접근할 수 없습니다. 그 이유는
- StaticMethod는 클래스 차원에서 동작하므로 InstanceField가 속한 객체가 무엇인지 모릅니다.
- StaticMethod는 객체 생성 없이 호출될 수 있으므로, 인스턴스 멤버가 존재하지 않을 수도 있습니다.
- 생성자에서의 동작
- Static 생성자는 클래스 차원에서 한 번만 호출되며, 클래스가 처음 참조될 때 실행됩니다.
- 이때 역시 객체가 생성되지 않은 상태이기 때문에, 인스턴스 멤버를 사용할 수 없습니다.
class MyClass
{
public int InstanceField = 10;
public static int StaticField = 20;
static MyClass()
{
// InstanceField = 30; // 오류 발생
StaticField = 40; // static 필드는 초기화 가능
}
}
- 설계원칙
- C#에서는 정적(static)과 비정적 멤버를 명확히 구분하여:
- 코드의 명확성: 정적 메서드에서 어떤 객체의 인스턴스를 사용할지 모호한 상황을 방지합니다.
- 메모리 관리 효율성: 정적 멤버는 객체 수와 상관없이 한 번만 메모리에 할당되므로 메모리를 절약할 수 있습니다.
○ 요약
static
멤버는 클래스 차원에서 관리되며, 특정 인스턴스와 연결되지 않습니다.
static
메서드에서는 인스턴스 멤버가 속한 객체를 참조할 방법이 없습니다.
- C#은 이러한 설계를 통해 코드의 명확성과 메모리 효율성을 높이고, 런타임 오류를 방지합니다.