2010-01-29 6 views
3

Object 클래스의 인스턴스를 선언하면 한 점에 대해 혼란 스럽습니다. 힙에 예약되지만, 선언 할 때 Object 클래스에서 파생 된 System.ValueType에서 파생 된 기본 유형 인스턴스가 있으면 Object 클래스에서 사용되는 부분도 스택에 예약됩니다.값 유형에 대한 혼동

왜 그런가요? 그렇지 않으면 Object 클래스에 공간이 필요하지 않습니까?

+3

Skeet 읽기 : http://www.yoda.arachsys.com/csharp/parameters.html –

+1

이 질문에 대한 내 대답은 도움이 될 수 있습니다. http://stackoverflow.com/questions/1978589/why-do-structs -need-to-be-boxed –

+0

@Mehrdad, 당신의 설명은 매우 도움이되었는데, 매우 흥미 롭다. 저수준에서는 가치가 상속받지 못한다. 그것은 주요 문제 였고, 나는 그것의 기본 클래스이고 System.Object의 일부 개인 데이터가 있어야한다는 점에서 System.Object를 그 부분으로 가질 것이라고 가정하고있었습니다. – waheed

답변

6

당신의 추론은 다음과 같이 갈 것 같다

선택 System.Int32이하는 System.Object에서 파생
  • 파생 형은 항상 기본 형식과 같은 방법으로 메모리에 배치되어
  • 따라서 System.Int32는 System.Object와 동일한 메모리에 배치됩니다.

예?

두 번째 전제는 거짓입니다. 파생 및 메모리 레이아웃은 서로 할 일이 거의 없습니다. 이 전제가 사실이라고 믿습니까? 그렇다면 무엇 때문에 당신이 그것을 믿었습니까?

업데이트 : 값 유형의 메소드 호출이 어떻게 작동하는지 설명하는 것이 도움이 될 것이라고 생각합니다.

struct S { 
    public int x; 
    public override string ToString() { return "Hello!" + x; } 
} 
... 
S s = new S(); 
s.x = 0x00112233; 
s.ToString(); 

우리가 어떤 코드를 생성 않습니다

는 값 형식을 가지고 가정? 코드는 다음을 수행합니다.

  • 은 s.x의 스택에서 4 바이트를 예약합니다.
  • 바이트 00 11 22 33을 해당 메모리에 씁니다.
  • S.ToString 메서드를 호출하여 방금 스택에 할당 한 메모리 위치에 대한 참조를 전달합니다.

왜 s.x의 4 바이트 이외의 것을 스택에 저장해야합니까? 우리는 호출을하기 위해 이미 필요한 모든 것을 가지고 있습니다 : S의 인스턴스를 포함하는 변수에 대한 참조, 그리고 우리가 호출하는 정확한 메소드 구현의 정확한 이름과 위치. System.Object와 관련이있는 것을 저장할 필요가 없습니다. "객체 클래스에서 사용하는 부분"이 없습니다. 우리에게는 그러한 일이 필요 없기 때문에 그러한 일은 없습니다.

+0

네, 그건 내가 생각하는 방식 인 것 같습니다. 그 이유는 하나의 개체 (하나의 장소 (즉, 스택 또는 힙)에있을 것이라고 가정하면서, 개체를 단일 엔터티로 간주하기 때문입니다. – waheed

2

종종 Eric Lippert의 블로그 the stack is an implementation detail을 참조하십시오. 가치 유형의 본질적인 특성은 가치에 의해 전달된다는 것입니다. System.ValueType 실제로 System.Object에서 상속 있지만 값 형식을 특별한 방식으로 처리 할 말할 수 있습니다. 그들은 항상 값으로 복사됩니다.

+0

Eric Lippert의 블로그가 정말 도움이되었습니다. 감사합니다. – waheed

3

.Net 값 유형은 입니다. 항상이 스택에 할당됩니다. 권리?

아니, 미안하지만 항상

당신이 함수에서 지역 변수와 같은 값 유형을 선언 할 경우, 예, 그것은 스택에 할당 할 수 없습니다.

값 유형이 클래스의 멤버이면 객체의 일부로 힙에 저장됩니다.

+1

P. 실제로 Jon Skeet은 작년에이 시간에 대해 이것을 설명했습니다. Thanks Yon :) –

+3

로컬 변수가 반복자 블록에 있거나 익명 메소드 또는 람다 식의 닫혀진 외부 변수가 아니면. –

+0

@ Eric Lippert : 감사합니다. –

0

ValueType에서 파생되는 것은 컴파일러에서 다르게 처리됩니다. 힙에 객체로 할당되지 않고 인라인으로 할당됩니다. 즉 스택의 로컬 변수 또는 다른 객체의 멤버로 할당됩니다.

값 유형에는 오브젝트가 가진 추가 데이터가 없습니다. 객체에는 유형 식별자와 가상 메소드 테이블에 대한 참조가 있지만 값 유형에는 이러한 유형 중 하나가 필요하지 않습니다. 예를 들어, Int32는 실제 데이터에 대해 4 바이트 만 필요합니다.

관련 문제