struct TestST
{
public int a;
}
public class MyList
{
static void TestFunc(TestST data) { data.a = 1000; }
static void Main(string[] args)
{
TestST testST = new TestST();
testST.a = 100;
}
}
이런경우라 해보자
TestFunc가 지금은 struct를 인자로 받는데
class를 받는 경우 인자로 넘어간 객체의 변수값이 변경이 될 것이다.
그런데 struct는 값이 변경이 안된다.
데이터는
"참조형"
"값형"
클래스를 객체화하면 그것은 => "참조형" (힙에 올라가고 객체 변수가 그곳을 가르킨다)
Main함수안에 이 내용임.
클래스는
이런 모양이다.
구조체는 뭐다?
"값 형식"이다. (== 값 유형)
아~ 그러면 Main함수 안에 구조체의 객체를
new 연산자를 통해만들었다면 (진짜는 힙에)
(new연산자는 객체를 만들고 생성자를 호출한다)
스택에 구조체의 객체가 들어가겠네~~ 인데
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗
값형식을 new연산자를 통해 만들었기 때문에
testST의 객체가 만들어지고 생성자를 호출을 한다.
그런데 testST의 객체를 만들긴 했는데 "값형식"이라 힙에 데이터가 올라가지 않고
"스택"에 올라간다.
그래서 아까와 같은
struct TestST
{
public int a;
}
public class MyList
{
static void TestFunc(TestST data) { data.a = 1000; }
static void Main(string[] args)
{
TestST testST = new TestST();
testST.a = 100;
TestFunc(testST);
}
}
이런경우 TestST구조체의 객체를 testST로 new연산자를 통해서 만들면
구조체라 값형식이고 값형식이기 때문에 main함수 스택영역에서 객체가 생성되어 만들어진다.
이루 TestFunc에 인자로 testST를 넘겨주어도
TestFunc만의 지역변수 구조체인 data의 지역변수인 a의 값을 수정하게되고
인자로넘겨준 testST의 지역변수인 a는 값이 수정되지 않는다.
만약 넘겨준것이 구조체가 아니라 int a같은거라고 생각해봐라.
https://kukuta.tistory.com/385
'참조' 타입과 '값' 타입(Reference Types and Value Types)
'참조 타입(reference type)'이란 인스턴스가 힙 영역에 할당 되고 해당 유형의 변수가 힙에 할당 되어 있는 객체를 가리키고 있는 포인터임을 의미한다. C#에서 class는 참조 타입으로 생성되며 모두 힙 영역에 메모리가 할당 된다.
C#은 프로그래밍의 단순함을 위해 C++과 같은 프로그래밍 언어에서 사용되는 포인터를 없애려고하지만 실제로는 C++보다 더 광범위하게 포인터를 사용한다. 아이러니하게도 포인터를 없애려는 욕망은 대다수의 변수가 - 내부적으로 - 포인터역할을 하는 시스템을 만들었다. class 유형인 모든 변수는 실제로 포인터이며 이것이 대부분의 C# 변수에 대해 null 검사를 해야하는 이유다.
객체 자체가 메모리를 차지하는것 외에도 class 에는 몇가지 추가 메모리 오버헤드가 있다. class 객체에 대한 모든 변수는 실제로는 포인터이므로 해당 포인터는 64비트 프로그램에서 8바이트를 차지한다. 또한 일부 데이터(64비트 프로그램에서는 16바이트)는 가비지 콜렉팅등을 위한 내부적인 목적으로 추가 저장된다.
반면에 C#에서 구조체(struct)는 '값 타입(value type)'이다. 값 타입의 변수는 객체에 대한 포인터가 아니라 객체 자체다. struct를 함수의 로컬 변수로 생성하면 해당 객체는 스택 메모리 영역에 할당 된다. 만일 구조체가 클래스의 멤버 변수로써 생성된다면 클래스와 같이 힙 메모리에 클래스 객체의 일부로써 할당 된다.
C#의 구조체(struct)는 C++의 값 타입(비포인터 변수)과 매우 비슷하게 작동한다. 할당 작업을 수행하면 복사본이 만들어지며, 함수에 인자로써 전달될 때 역시 참조로써 전달하지 않으면 복사복이 생성되어 전달 된다. 물론 복사복을 수정해도 원본은 수정되지 않느다. 구조체 변수는 null 검사가 필요하지 않다. 흥미롭게도 C#은 포인터를 지원하지 않기 때문에 구조체 객체에 대한 '포인터'를 가질 수 없다(함수에 참조로 전달하는 것 제외).
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct
class
struct
enum
세가지 있다.
CPP에서는 enum : 정수형 상수 라고하는데
C#에서는 아니다.
비슷한데
C++ 에서는 정수 상수 집합이고
C#에서는 가본 정수 숫자 유형의 명명된 상수 집합 => 그냥 상수이다.
시발?
https://boycoding.tistory.com/179
=> 아마도 가장 간단한 사용자 정의 자료형은 열거된 유형일 것이다. 열거된 유형(열거형이라고도 함)은 가능한 모든 값이 기호 상수(열거형)로 정의되는 자료형이다. 열거형은 enum 키워드를 통해 정의된다.
여기서 "모든 값이 상수"라고하는데
상수 = constant => 변경되지 않는다.
상수(constant)란 변수와 마찬가지로 데이터를 저장할 수 있는 메모리 공간을 의미합니다.
하지만 상수가 변수와 다른 점은 프로그램이 실행되는 동안 상수에 저장된 데이터는 변경할 수 없다는 점입니다.
그러면 CPP에서의 사용자 정의 자료형 enum은 정수형 상수인데
C#에서는 다르단다. ㅇㅋ?
class : 참조형 사용자 정의
struct : 값형 사용자 정의
enum : 값형 사용자 정의