글 작성자: Doublsb

문제 상황

 

나는 여느 때처럼 클래스 객체를 사용해 다른 함수에게 데이터를 넘겨주고 있었다.

public class Tester : MonoBehaviour
    {
        private void Start()
        {
            var data = new Data();
            Initialize(data);
        }

        public void Initialize(Data data)
        {
            //Something
        }
    }

    public class Data
    {
        public int crushId = -1;
        public int count = 0;

        public Data(int crushId = -1, int count = 0)
        {
            this.crushId = crushId;
            this.count = count;
        }
    }

 

 

그런데, 클래스 객체가 이곳저곳에 호출되면서 중간에 객체의 내용이 변경되어 전달되는 문제가 생겼다.

이를 해결하기 위해 클래스를 구조체로 변경하여 전달하기로 했다.

 

public struct Data
{
    public int crushId;
    public int count;

    public Data(int crushId = -1, int count = 0)
    {
        this.crushId = crushId;
        this.count = count;
    }
}

 

그리고 평소처럼 파라미터 없이 구조체 객체를 만들어 전달했더니...

 

당당하게도 새로 만들어진 구조체 객체는 crushId로 0을 들고 있는 것이 아닌가!

디버깅을 해 보니 내가 만들어 놓은 생성자는 호출도 안 되고 있었다. 대체 어떻게 된 것이지?

 

private void Start()
{
    var data = new Data();

    print(data.crushId);
    print(data.count);
}

 


 

이유

 

구조체가 값 형식이고, C#은 구조체의 자체적인 기본 생성자를 가지고 있기 때문에 생기는 오류다.

실제로, 아무 파라미터도 없는 생성자를 구조체에서 생성하려고 하면 다음과 같은 오류가 발생한다.

오류 CS0568	구조체는 매개 변수가 없는 명시적 생성자를 포함할 수 없습니다.

 

이 자체적인 기본 생성자는 구조체의 모든 필드 값을 기본값으로 설정하여 생성한다.

그러므로 int값의 필드는 모두 0이 되어 나왔던 것.

 

그렇다면 왜 구조체에서 파라미터 없는 생성자를 만들지 못하게 했을까?

스택 오버플로우에서 유저들이 토론하는 스레드를 발견할 수 있었다.

https://stackoverflow.com/questions/333829/why-cant-i-define-a-default-constructor-for-a-struct-in-net

 

Why can't I define a default constructor for a struct in .NET?

In .NET, a value type (C# struct) can't have a constructor with no parameters. According to this post this is mandated by the CLI specification. What happens is that for every value-type a default

stackoverflow.com

 

가장 추천 수가 많은 사람의 의견으로는, 값 형식인 구조체를 매번 생성자를 사용하여 초기화하는 것이 효율적이지 않다는 것이다.

MyStruct[] foo = new MyStruct[1000];

이 상황에서, 새롭게 생성되는 MyStruct 객체 1000개는 모두 생성자를 부르면서 생성되어야 하는가?

 

만약 MyStruct가 구조체가 아니라 클래스였다면, 저 1000개의 객체는 모두 Null이 될 것이라고 예상했을 것이다.

그러나 구조체는 참조 타입이 아니라 값 타입이므로 필드를 어떻게든 모두 만들어내야만 하므로, 기본 생성자가 없다면 비효율적인 상황이 만들어지게 될 것이다.

 

 


 

해결 방법

 

간단하다.

생성자를 이용해 구조체를 초기화하고 싶다면 파라미터 없이 부르지 말자.

반응형

'프로그래밍 > C#' 카테고리의 다른 글

C# 9.0 새 기능 알아보기  (0) 2023.01.16
C# 8.0 새 기능 알아보기  (0) 2022.09.20
Enum.ToString 최적화하기  (0) 2022.02.25
[.Net C# 설명서] 읽고 정리하기  (0) 2021.09.29
[C# 코딩의 기술]에서 얻은 지식들  (0) 2021.09.24