심층 분석 : .Net의 값 및 참조 유형

Microsoft .Net의 유형은 값 유형 또는 참조 유형일 수 있습니다. 값 유형은 일반적으로 스택에 저장되지만 참조 유형은 관리되는 힙에 저장됩니다.

값 형식은 System.ValueType에서 파생되며 자체 메모리 할당 내에 데이터를 포함합니다. 즉, 변수 나 객체 또는 값 유형에는 자체 데이터 사본이 있습니다.

한편 참조 유형은 System.Object를 확장하고 실제 데이터가 포함 된 메모리의 위치를 ​​가리 킵니다. 포인터에 액세스 할 때 암시 적으로 역 참조되는 포인터와 유사한 참조 유형을 상상할 수 있습니다. C #에서 지원하는 기본 제공 참조 유형에는 개체, 문자열 및 동적이 포함됩니다. 모든 기본 데이터 유형, 부울, 날짜, 구조체 및 열거는 값 유형의 예입니다. 참조 형식의 예로는 문자열, 배열, 클래스 개체 등이 있습니다. C #에서 참조 형식을 만들려면 class, interface, delegate 키워드를 활용할 수 있습니다.

참조 유형과 달리 값 유형에서 파생 될 수 없으며 값 유형에 직접 null 값을 할당 할 수도 없습니다. .Net Framework의 최신 버전에 추가 된 기능인 nullable 형식을 활용해야만 값 형식에 null 값을 할당 할 수 있습니다. 값 유형이 다른 유형으로 복사되면 값이 복사됩니다. 따라서 다른 값과 독립적으로 값을 조작 할 수 있습니다. 반대로 참조 유형을 다른 유형으로 복사하면 참조가 복사됩니다. 이들 중 하나를 변경하면 다른 하나도 영향을받습니다. 예를 들어 참조 중 하나가 널로 설정되면 다른 하나도 널이됩니다.

보관 장소

CLR은 레지스터, 스택 또는 관리되는 힙의 세 가지 유형의 저장소 위치에 개체를 저장합니다. 수명이 짧은 개체는 레지스터 또는 스택에 저장되지만 수명이 긴 개체는 힙에 저장됩니다. 앞서 언급했듯이 값 유형은 일반적으로 스택에 저장됩니다.

값 유형이 항상 스택에 저장된다는 것은 일반적인 오해입니다. 차라리 변수가 임시 변수이거나 지역 변수이고 JIT 컴파일러가 값을 등록하지 않기로 결정할 때 값 유형 스택에 저장할 있다고 말하고 싶습니다 . 본질적으로 값 유형의 실제 위치는 JIT 컴파일러의 구현에 따라 다릅니다. 값 유형은 스택 프레임, CPU 레지스터 또는 값 유형이 객체 내부에 포함 된 경우 (예 : 참조 유형의 일부인 경우) 힙 메모리에 저장할 수 있습니다. 반대로 참조 유형은 GC 힙에 저장됩니다. 객체가 힙에 할당되는 동안 참조는 스택에 저장됩니다.

값 유형의 인스턴스 또는 참조는 인스턴스 또는 참조의 수명이 단기인지 장기인지에 따라 스택, 레지스터 또는 힙에 저장됩니다. 값 유형은 로컬 변수 인 경우 스택에 상주 할 수 있고 클래스의 필드 인 경우 관리되는 힙에있을 수 있습니다 (예 : 참조 유형에 속하거나 일부인 경우).

값으로 전달하고 참조로 전달

다음 코드 목록은 값으로 메소드에 변수를 전달하는 방법을 보여줍니다.

 static void Increment(int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

ref 키워드를 사용하여 값 형식을 메서드에 대한 참조로 전달할 수 있습니다. 다음 코드 목록은이를 보여줍니다.

static void Increment(ref int i)

        {

            i = i + 1;

        }

        static void Main()

        {

            int x = 1;

            Increment(ref x);

            Console.WriteLine("The value of x is: " +x);

            Console.Read();

        }

위의 코드가 실행되면 콘솔에 "The value of x is : 2"라는 메시지가 표시됩니다.

권투 및 개봉

값 유형을 참조 유형으로 변환하는 것을 권투라고합니다. Unboxing은 그 반대입니다. 참조 유형을 값 유형으로 변환하는 프로세스로 정의됩니다. 다음 코드 조각은 C #의 boxing 및 unboxing을 보여줍니다.

int i = 100;

Object obj = i; //Boxing

i = (int) obj; //Unboxing