2019년 10월 5일 토요일

C#의 프로퍼티(Property of C#)

OOP 프로그램의 특징 중 하나인 capsulation을 위해 대부분 정보값을 얻는 함수와 쓰는 함수를 함께 만들어야 합니다.

class Student
{
private :
    int studentNo;
    char name[32];
public :
    int GetStudentNo()
    {
        return studentNo;
    }
    char *GetName()
    {
        return name;
    }
};

멤버의 정보를 은닉한 덕에, 정보를 얻기 위해서는 항상 멤버에 접근하는 함수가 있어야 합니다.

그래서 C#에서는 아예 은닉된 정보에 접근하는 property라는 개념을 만들었죠.

// 가
public class Student
{
    private int studentNo;
    public int StudentNo
    {
        get
        {
            return studentNo;
        }
        private set
        {
            studentNo = value;
        }
    }
    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        private set
        {
            name = value;
        }
    }
}

이것이 번거롭다면 다음과 같이 프로퍼티를 간단하게 만들 수도 있습니다.

// 나
public class Student
{
    private int StudentNo { get; private set; }
    private string Name { get; private set; }
}

겉보기에는 의 방법과 의 방법이 크게 다르지 않습니다. 둘 다 다음과 같은 방식으로 쓸 수 있죠.

publc StudentFunction(Student student)
{
    int no = student.StudentNo;    // 학생번호 얻어오기
    student.StudentNo = 12345;     // private멤버에 접근(set) 불가
}


그렇다면 이 두 가지 방법이 어떻게 다를까요?

먼저 의 방법은 정수형 studentNo와 문자열형 name이라는 멤버변수를 만들고 각각에 해당하는 StudentNo와 Name이라는 프로퍼티를 만듧니다. 그 때문에 일반변수인 student를 사용할 수 있습니다. ref나 out을 붙여서 쓸 수 있다는 말이죠.


// 가
public class Student
{
    private int studentNo;
    public int StudentNo
    {
        get
        {
            return studentNo;
        }
        private set
        {
            studentNo = value;
        }
    }
    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        private set
        {
            name = value;
        }
    }
    public Student()
    {
        Reader(out studentNo, out name);
    }
}




의 경우, 멤버변수를 생략하고 프로퍼티만 표현한 것으로, 내부적으로는 다음과 같이 표현됩니다.

// 나
public class Student
{
    private int _s3DRfxD4Se;  // 컴파일러가 만든 변수
    public int StudentNo
    {
        get
        {
            return _s3DRfxD4Se;
        }
        private set
        {
            _s3DRfxD4Se = value;
        }
    }
    private string _y7FdV4Ee;  // 컴파일러가 만든 변수
    public string Name
    {
        get
        {
            return _y7FdV4Ee;
        }
        private set
        {
            _y7FdV4Ee = value;
        }
    }
}

즉 컴파일러가 자기 맘대로 이름을 정해 변수를 만든 후 위와 같은 정형화된 코드를 만들어내는 것입니다.
이때 우리는 프로퍼티의 이름을 알 뿐 컴파일러가 만든 변수의 이름을 알지 못합니다. 그러므로 의 경우와 같이 변수의 참조를 사용할 수 없습니다.


// 나
public class Student
{
    private int StudentNo { get; private set; }
    private string Name { get; private set; }

    public Student()
    {
        Reader(out StudentNo, out Name);  // 컴파일 에러
    }
}