몇 달 전에 어떤 사람이이 질문을했지만 자세히 설명 할 수 없었습니다. C #에서 참조 형식과 값 형식의 차이점은 무엇입니까?
나는 그 값 유형을 알고 int
, bool
, float
, 등 참조 유형은 delegate
, interface
, 등 또는도이 잘못?
전문적인 방식으로 설명해 주시겠습니까?
답변
귀하의 예 때문에 동안 약간의 홀수 int
, bool
및 float
특정 유형, 인터페이스 및 대의원이 있습니다 가지 유형의 – 단지 같은 struct
과 enum
값 형식의 종류입니다.
이 기사에서 참조 유형 및 값 유형 에 대한 설명을 작성 했습니다 . 혼란스러워하는 부분이 있으면 기꺼이 확장하겠습니다.
“TL; DR”버전은 특정 유형의 변수 / 표현식 값이 무엇인지 생각하는 것입니다. 값 유형의 경우 값은 정보 자체입니다. 참조 유형의 경우 값은 null 일 수있는 참조이거나 정보를 포함하는 개체를 탐색하는 방법 일 수 있습니다.
예를 들어, 변수를 종이처럼 생각하십시오. “5”또는 “false”라는 값이 적혀있을 수 있지만 내 집은 가질 수 없습니다 . 내 집 으로 가는 길 을 알려야합니다. 이러한 지침은 참조와 동일합니다. 특히 두 사람이 내 집으로가는 방향이 같은 다른 종이를 가지고있을 수 있습니다. 한 사람이 그 길을 따라 내 집을 빨간색으로 칠하면 두 번째 사람도 그 변화를 볼 수 있습니다. 둘 다 종이에 내 집 사진 을 따로 찍었 다면 한 사람이 종이에 색칠을하더라도 다른 사람의 종이를 전혀 바꾸지 않을 것입니다.
답변
값 유형 :
메모리 주소가 아닌 일부 값을 보유합니다.
예:
구조
저장:
TL; DR : 변수의 값은 해제 될 때마다 저장됩니다. 지역 변수는 예를 들어 스택에 살고 있지만 구성원으로 클래스 내에 선언 때 단단히가 선언 된 클래스와 결합 된 힙에 살고있다.
긴 : 그들이 선언 된 곳 따라서 값 유형이 저장됩니다. 예 : int
지역 변수로서 함수 내부의의 값은 스택에 저장되는 반면 int
, 클래스의 멤버로 선언 된 in의 값은 선언 된 클래스와 함께 힙에 저장됩니다. 클래스에는 선언 된 클래스와 정확히 동일한 라이프 타입이 있으므로 가비지 수집기의 작업이 거의 필요하지 않습니다. 하지만 더 복잡합니다. @JonSkeet의 책 ” C # In Depth “를 참조하겠습니다.보다 간결한 설명을 위해 .NET의 메모리 “
장점 :
값 유형에는 추가 가비지 콜렉션이 필요하지 않습니다. 그것은 존재하는 인스턴스와 함께 가비지 수집을 가져옵니다. 메서드의 지역 변수는 메서드를 떠날 때 정리됩니다.
단점 :
-
큰 값 집합이 메서드에 전달되면 수신 변수가 실제로 복사하므로 메모리에 두 개의 중복 값이 있습니다.
-
수업을 놓치면 모든 oop 혜택이 손실됩니다.
참조 유형 :
값이 아닌 값의 메모리 주소를 보유합니다.
예:
수업
저장:
힙에 저장
장점 :
-
참조 변수를 메소드에 전달하면 실제로 원래 값이 변경되는 반면 값 유형에서는 주어진 변수의 사본이 취해져 그 값이 변경됩니다.
-
변수의 크기가 클 때 참조 형이 좋다
-
클래스는 참조 유형 변수로 제공되므로 재사용 가능성을 제공하므로 객체 지향 프로그래밍에 도움이됩니다.
단점 :
값을 읽을 때 할당 및 역 참조시 더 많은 작업 참조 가비지 수집기에 대한 추가 오버로드
답변
컴퓨터가 메모리에 물건을 할당하는 방법을 알고 포인터가 무엇인지 안다면 두 가지의 차이점을 더 쉽게 이해할 수있었습니다.
참조는 일반적으로 포인터와 연관됩니다. 변수가있는 메모리 주소가 실제로 다른 메모리 위치에있는 실제 객체의 다른 메모리 주소 를 보유하고 있음을 의미합니다 .
제가 드리려고하는 예는 지나치게 단순화되어 있으므로 소금 한 알과 함께 가져 가십시오.
컴퓨터 메모리가 내부에 무언가를 담을 수있는 한 줄의 사서함 (PO Box 0001부터 PO Box n으로 시작)이라고 상상해보십시오. 사서함이 당신을 위해 그것을하지 않으면 해시 테이블이나 사전 또는 배열 또는 유사한 것을 시도하십시오.
따라서 다음과 같은 작업을 수행 할 때 :
var a = “Hello”;
컴퓨터는 다음을 수행합니다.
- 메모리를 할당하고 (예를 들어 메모리 위치 1000에서 5 바이트로 시작) H (1000에서), e (1001에서), l (1002에서), l (1003에서) 및 o (1004에서)를 입력합니다.
- 메모리 어딘가 (예 : 0500 위치)에 할당하고 변수 a로 할당합니다.
그래서 그것은 일종의 별칭과 같습니다 (0500은 a). - 해당 메모리 위치 (0500)의 값을 1000 (문자열 Hello가 메모리에서 시작하는 위치)에 할당합니다. 따라서 변수 a는 “Hello”문자열의 실제 시작 메모리 위치에 대한 참조 를 보유 합니다.
값 유형은 실제 사물을 메모리 위치에 보관합니다.
따라서 다음과 같은 작업을 수행 할 때 :
var a = 1;
컴퓨터는 다음을 수행합니다.
- 0500에 메모리 위치를 할당하고 변수 a에 할당하십시오 (동일한 별칭)
- 그 안에 값 1을 넣으십시오 (메모리 위치 0500).
실제 값 (1)을 유지하기 위해 추가 메모리를 할당하지 않습니다. 따라서 a는 실제로 실제 값을 보유하고 있기 때문에 값 유형이라고합니다.
답변
이것은 약 2 년 전 다른 포럼의 제 게시물입니다. 언어는 vb.net (C #과 반대)이지만 값 유형 대 참조 유형 개념은 .net 전체에서 동일하며 예제는 여전히 유지됩니다.
.net 내에서 모든 유형은 기술적으로 기본 유형 Object에서 파생된다는 사실을 기억하는 것도 중요합니다. 값 유형은 그렇게 작동하도록 설계되었지만 결국 기본 유형 Object의 기능도 상속합니다.
A. 값 유형은 메모리에서 개별 값이 저장되는 고유 한 영역을 나타냅니다. 값 유형은 고정 된 메모리 크기이며 고정 된 크기의 주소 모음 인 스택에 저장됩니다.
다음과 같은 진술을 할 때 :
Dim A as Integer
DIm B as Integer
A = 3
B = A
다음을 수행했습니다.
- 32 비트 정수 값을 보유하기에 충분한 메모리에 2 개의 공간을 생성했습니다.
- A에 할당 된 메모리 할당에 값 3을 배치했습니다.
- A에 보유 된 것과 동일한 값을 할당하여 B에 할당 된 메모리 할당에 값 3을 배치했습니다.
각 변수의 값은 각 메모리 위치에 개별적으로 존재합니다.
B. 참조 유형은 다양한 크기가 될 수 있습니다. 따라서 “스택”에 저장할 수 없습니다 (스택이 고정 된 크기의 메모리 할당 모음임을 기억하십니까?). 이들은 “관리되는 힙”에 저장됩니다. 관리되는 힙의 각 항목에 대한 포인터 (또는 “참조”)는 스택 (예 : 주소)에서 유지됩니다. 코드는 스택에서 이러한 포인터를 사용하여 관리되는 힙에 저장된 개체에 액세스합니다. 따라서 코드에서 참조 변수를 사용할 때 실제로 포인터 (또는 관리되는 힙의 메모리 위치에 대한 “주소”)를 사용합니다.
문자열 Property Person.Name을 사용하여 clsPerson이라는 클래스를 만들었다 고 가정 해 보겠습니다.
이 경우 다음과 같은 진술을 할 때 :
Dim p1 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"
Dim p2 As Person
p2 = p1
위의 경우 p1.Name 속성은 예상대로 “Jim Morrison”을 반환합니다. p2.Name 속성은 직관적으로 예상하는 것처럼 “Jim Morrison”도 반환합니다. 나는 p1과 p2가 모두 스택에서 별개의 주소를 나타낸다고 생각합니다. 그러나 이제 p2에 p1 값을 지정 했으므로 p1과 p2는 모두 관리되는 힙의 동일한 위치를 가리 킵니다.
이제 다음 상황을 고려하십시오.
Dim p1 As clsPerson
Dim p2 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"
p2 = p1
p2.Name = "Janis Joplin"
이 상황에서 개체를 참조하는 스택의 포인터 p1을 사용하여 Managed Heap에 사람 클래스의 새 인스턴스 하나를 만들고 개체 인스턴스의 Name 속성에 “Jim Morrison”값을 다시 할당했습니다. 다음으로 스택에 또 다른 포인터 p2를 생성하고 p1이 참조하는 것과 동일한 주소를 관리되는 힙에 지정했습니다 (할당 p2 = p1을 만들 때).
여기에 트위스트가 있습니다. p2의 Name 속성에 “Janis Joplin”값을 할당하면 다음 코드를 실행 한 경우 p1과 p2가 모두 참조하는 개체의 Name 속성이 변경됩니다.
MsgBox(P1.Name)
'Will return "Janis Joplin"
MsgBox(p2.Name)
'will ALSO return "Janis Joplin"Because both variables (Pointers on the Stack) reference the SAME OBJECT in memory (an Address on the Managed Heap).
그게 말이 되었나요?
마지막. 이렇게하면 :
DIm p1 As New clsPerson
Dim p2 As New clsPerson
p1.Name = "Jim Morrison"
p2.Name = "Janis Joplin"
이제 두 개의 별개의 Person Object가 있습니다. 그러나이 작업을 다시 수행하는 순간 :
p2 = p1
이제 두 가지 모두 “Jim Morrison”을 가리 켰습니다. (나는 p2가 참조하는 힙의 객체에 무슨 일이 일어 났는지 정확히 모르겠습니다… 나는 그것이 이제 범위를 벗어났다고 생각합니다. 이것은 누군가가 나를 바로 잡을 수있는 영역 중 하나입니다…). -편집 : 나는 이것이 새로운 할당을 만들기 전에 p2 = Nothing OR p2 = New clsPerson을 설정하는 이유라고 믿습니다.
다시 한 번, 지금 이렇게하면 :
p2.Name = "Jimi Hendrix"
MsgBox(p1.Name)
MsgBox(p2.Name)
이제 두 msgBox 모두 “Jimi Hendrix”를 반환합니다.
이것은 약간 혼란 스러울 수 있으며, 마지막으로 한 번 말씀 드리겠습니다. 세부 사항 중 일부가 잘못되었을 수 있습니다.
행운을 빕니다. 저보다 더 잘 아는 다른 사람들이이 중 일부를 명확히하는 데 도움이되기를 바랍니다. . .
답변
값 데이터 유형 및 참조 데이터 유형
1) 값 (데이터를 직접 포함)하지만
참조 (데이터를 나타냄)
2)에 값 (모든 변수는 그 자신의 복사본이 있음)하지만
의 기준 (기타 변수가 어떤 오브젝트를 참조 할 수있는 것보다)
3) 값 (작업 변수는 다른 변수에 영향을 줄 수 없음 )이지만 참조 (변수는 다른 변수에 영향을 줄 수 있음)
4) 값 유형 은 (int, bool, float)이지만
참조 유형 은 (array, class objects, string)
답변
값 유형 :
-
고정 메모리 크기.
-
스택 메모리에 저장됩니다.
-
실제 값을 보유합니다.
전의. int, char, bool 등 …
참조 유형 :
-
고정 메모리가 아닙니다.
-
힙 메모리에 저장됩니다.
-
실제 값의 메모리 주소를 저장합니다.
전의. 문자열, 배열, 클래스 등 …