값 타입 생성자는 참조 타입 생성자와 다르게 아래와 같은 특징이 있다.
값 타입에서는 필드 초기화를 사용할 수 없다. 그 이유는 앞서 설명한 값 타입 생성자의 특징 중 하나인 '인자가 없는 생성자를 만들 수 없다.'는 특징 때문이다.
struct SPoint
{
public int x = 0;
public int y = 0;
}
struct SPoint
{
public int x;
public int y;
public SPoint()
{
x = 0; y = 0;
}
}
참조 타입의 경우 컴파일러가 각 필드의 초기값이 있을 때 인자가 없는 생성자를 생성하는데 이부분이 제약에 어긋나기 때문에 필드 초기화를 사용할 수 없는 것이다.
최신 버전의 C#(10 버전 이상)에서 해당 기능을 제공한다고 한다. 즉, 값 타입에 기본 생성자를 정의할 수 있고 필드 초기화가 가능하다고 한다.
값 타입 객체를 생성하는 것과 생성 후 초기화 하는 것에는 차이가 있는데 둘다 메모리에는 있지만 초기화가 되어 있지 않아 실제 사용을 못하는 경우가 생길 수 있다.
아래 코드를 보면 p1이 초기화 되어 있지 않아 컴파일 에러가 발생하는 것을 볼 수 있다.
public static void Main(string[] args)
{
SPoint p1;
SPoint p2 = new SPoint();
Console.WriteLine($"{p1.x}"); // Error!
Console.WriteLine($"{p2.x}"); // Ok!
p1.x = 1;
Console.WriteLine($"{p1.x}"); // Ok!
Console.WriteLine($"{p2.x}"); // Ok!
}
그리고 값 타입의 생성자에서 기본 파라미터를 사용하면 초기화가 되지 않는 상황이 발생할 수 있다. 그 이유는 컴파일러가 생성자를 호출할 때 기본 매개변수가 있는 생성자가 아닌 기본 생성자를 호출하기 때문이다. 아래 코드를 보면 출력값이 0, 0이 되는 것을 볼 수 있다.
struct SPoint
{
public int x;
public int y;
public SPoint(int x = 2, int y = 1)
{
this.x = x;
this.y = y;
}
}
public static void Main(string[] args)
{
SPoint p1;
SPoint p2 = new SPoint(); // 기본 매개변수 생성자? 기본 생성자?
Console.WriteLine($"{p2.x}, {p2.y}"); // 0, 0
}

아래와 같은 기본 생성자를 만들고 실행하면 3, 2가 출력되는 것을 보면 확실히 기본 생성자가 출력되는 것으로 생각할 수 있다.
public SPoint()
{
this.x = 3;
this.y = 2;
}
