[C#] 5.1 캡슐화 대상(5.1.5 생성자)

생성자는 정의한 클래스나 구조체의 개체가 생성될 때 수행할 코드를 작성하는 메서드입니다. 생성자는 반환 형식을 명시할 수 없고 형식 이름과 같은 이름을 갖는 특별한 메서드입니다. C#에서 정의할 수 있는 생성자 종류에는 기본 생성자, 입력 매개 변수가 있는 생성자, 정적 생성자가 있습니다.

기본 생성자는 입력 매개 변수가 없는 생성자를 말합니다. 기본 생성자는 클래스에서만 명시적으로 정의할 수 있으며 구조체는 매개 변수 있는 생성자만 정의할 수 있습니다. 또한, 클래스나 구조체 내에 어떠한 생성자도 정의하지 않으면 묵시적으로 기본 생성자가 만들어지며 멤버들을 기본값으로 초기화하는 등의 작업을 수행합니다.

구조체에 명시적으로 기본 생성자 정의할 때 오류화면
[그림 15] 구조체에 명시적으로 기본 생성자 정의할 때 오류화면

▶ 생성자를 정의하지 않을 때

using System;
namespace Ex_Constructor
{
    class Example //생성자를 정의하지 않았음
    {
        public int Val
        {
            get;
            set;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Example ex = new Example(); 
            Console.WriteLine("ex.Val:{0}",ex.Val);
        }
    }
}

▶ 실행 결과

ex:Val:0

그리고 매개 변수가 있는 생성자를 정의하고 기본 생성자를 정의하지 않았을 때에는 컴파일러에 의해 기본 생성자가 만들어지지 않으므로 개체를 생성할 때 인자를 전달하지 않으면 오류가 발생합니다.

기본 생성자를 정의하지 않고 입력 인자없이 개체 생성시 오류 화면
[그림 16] 기본 생성자를 정의하지 않고 입력 인자없이 개체 생성시 오류 화면

 정적 생성자는 개체의 멤버가 아니라 정적 멤버입니다. 정적 멤버는 static 키워드를 명시하여 선언한 멤버를 말하며 사용할 때 형식명으로 접근합니다.

정적 생성자는 정적 멤버가 있을 때 정적 멤버들의 값을 초기화하거나 단 한 번만 수행되어야 하는 작업을 정의할 때 사용되며 직접 호출할 수 없으며 접근 한정자를 명시할 수도 없습니다. 그리고 정적 생성자는 해당 형식을 사용하는 어떤 코드보다도 먼저 수행됨을 보장합니다. 개체의 멤버와 정적인 멤버에 대한 자세한 사항은 5.3에서 다룰 것입니다.

▶ 정적 생성자가 호출되는 시점

using System;
namespace Ex_Constructor
{
    class Example
    {
        static Example() //접근 한정자를 명시할 수 없음
        {
            Console.WriteLine("정적 생성자 수행 ");
        }
        public static void Foo()
        {
            Console.WriteLine("정적 메서드 Foo 수행");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Example.Foo();
        }
    }
}

▶ 실행 결과

정적 생성자 수행
정적 메서드 Foo 수행

생성자의 접근 지정이 private으로 되어 있는 것을 전용 생성자라 부릅니다. 대표적인 예로 개체를 하나만 생성해야 할 때인데 GoF의 디자인 패턴에서는 싱글턴(Singleton) 패턴이라고 부릅니다.

▶ 전용 생성자를 이용해 단일체 구현

class Singleton
{
    static Singleton singleton; //단일체 정적 멤버 
    public static Singleton Instance //단일체를 참조할 때 사용하는 정적 속성
    {
        get
        {
            return singleton;
        }
    }
    static Singleton() //정적 생성자
    {
        singleton = new Singleton();//단일체 생성
    }
    private Singleton() //단일체로 구현하기 위해 접근 지정을 private 설정
    {
    }
}