[C#] 20. 프로퍼티 (Property)


Study/C#  2020. 7. 30. 17:52

안녕하세요. 명월입니다.


이 글은 C#에서의 프로퍼티(Property)에 대한 글입니다.


이전에 제가 OOP의 4대 특성과 접근 제한자와 캡슐화에 대해서 설명한 적이 있습니다.

링크 - [C#] 11. static과 접근 제한자 그리고 캡슐화

링크 - [C#] 19. 객체 지향(OOP) 프로그래밍의 4대 원칙(캡슐화, 추상화, 상속, 다형성)


기본적으로 객체 지향에서는 맴버 변수가 private로 지정해서 외부에서 접근을 금지합니다. 그렇다면 클래스의 맴버 변수의 값은 무조건 생성자나 내부에서만 등록을 하는 것인가 했을 때, 꼭 그렇지는 않고 함수를 통해서 변수의 값을 설정하거나 지정할 수 있습니다.

Java에서는 흔히들 getter, setter라고 이야기 하는 것입니다.

using System;

namespace Example
{
  // 클래스
  class Program
  {
    // 맴버 변수
    private int data;
    // 맴버 변수의 값을 설정하는 setter
    public void SetData(int data)
    {
      this.data = data;
    }
    // 맴버 변수의 값을 가져오는 getter
    public int GetData()
    {
      return this.data;
    }

    // 실행 함수
    public static void Main(string[] args)
    {
      // 인스턴스 생성
      Program p = new Program();
      // Program 인스턴스의 맴버 변수 data를 설정
      p.SetData(10);
      // Program 인스턴스의 맴버 변수를 취득해 콘솔 출력
      Console.WriteLine("p - data = " + p.GetData());

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

왜 이렇게 해야하는 것인가 하면 먼저 캡슐화를 위해 맴버 변수를 가리는 게 원칙입니다. 그리고 현재 getter, setter에 아무런 설정이 없습니다만 맴버 변수에 값을 취득하거나 설정을 제한할 수도 있습니다. 제한한다는 것이 함수의 여러가지 제어 조건을 설정할 수 있다는 뜻입니다.

그리고 맴버 변수를 public를 하면 설정, 취득을 제어할 수 없습니담나 getter만 설정하면 읽기 전용이 되고 setter만 설정하면 쓰기 전용이 됩니다.

그래서 객체 지향의 캡슐화를 위해 getter, setter가 이용됩니다.


C#에서는 이런 getter, setter를 좀 더 편하게 사용하기 위한 문법이 있는 데 그것이 프로퍼티(Property)입니다.

using System;

namespace Example
{
  // 클래스
  class Program
  {
    // 맴버 변수
    private int data;

    // 맴버 변수 data의 프로퍼티
    public int Data
    {
      // getter와 같은 취득 함수
      get
      {
        return this.data;
      }
      // setter와 같은 설정 함수
      set
      {
        // 설정 값은 value의 키워드로 들어온다.
        this.data = value;
      }
    }

    // 실행 함수
    public static void Main(string[] args)
    {
      // 인스턴스 생성
      Program p = new Program();
      // Program 인스턴스의 맴버 변수 data를 설정
      p.Data = 10;
      // Program 인스턴스의 맴버 변수를 취득해 콘솔 출력
      Console.WriteLine("p - data = " + p.Data);

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

보통 프로퍼티는 맴버 변수의 첫글자 대문자로 설정합니다. 그리고 자료형을 통해 getter, setter를 설정합니다.

스택 영역 안에서 get은 getter의 함수와 같고 set은 setter함수와 같습니다.

물론 get만 사용하면 읽기 전용이 되고 set만 사용하면 쓰기 전용이 됩니다.

using System;

namespace Example
{
  // 클래스
  class Program
  {
    // 맴버 변수
    private int data;

    // 맴버 변수 data의 프로퍼티
    public int Data
    {
      // getter와 같은 취득 함수
      get
      {
        return this.data;
      }
      // set을 제거하여 읽기 전용으로 만듬
    }

    // 실행 함수
    public static void Main(string[] args)
    {
      // 인스턴스 생성
      Program p = new Program();
      // 프로퍼티가 읽기 전용이라 설정이 되지 않는다.
      p.Data = 10;
      // Program 인스턴스의 맴버 변수를 취득해 콘솔 출력
      Console.WriteLine("p - data = " + p.Data);

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

그리고 프로퍼티의 접근 제한자는 기본적으로 get의 접근 제한자입니다. 즉, set의 접근 제한자만 별토로 설정할 수도 있습니다.

using System;

namespace Example
{
  // 클래스
  class Program
  {
    // 맴버 변수
    private int data;
    public Program()
    {
      // 프로퍼티를 통해 맴버 변수 설정
      this.Data = 10;
    }
    // 맴버 변수 data의 프로퍼티
    public int Data
    {
      // getter와 같은 취득 함수
      get
      {
        return this.data;
      }
      // setter와 같은 설정 함수, 접근 제한자를 내부와 상속받는 클래스만 되도록 설정
      protected set
      {
        // 설정 값은 value의 키워드로 들어온다.
        this.data = value;
      }
    }

    // 실행 함수
    public static void Main(string[] args)
    {
      // 인스턴스 생성
      Program p = new Program();
      // Program 인스턴스의 맴버 변수를 취득해 콘솔 출력
      Console.WriteLine("p - data = " + p.Data);

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

위 소스에서는 Data 프로퍼티의 set에만 접근 제한자를 설정했습니다.


프로퍼티의 역할은 정확히 맴버 변수의 제어입니다. 그런데 맴버 변수는 private로 고정 지정이기 때문에 크게 의미가 없어 보입니다. 그래서 이 맴버 변수가 C#에서는 생략이 가능합니다.

그럼 맴버 변수의 값을 어떻게 넣을까?

using System;

namespace Example
{
  // 클래스
  class Program
  {
    // 맴버 변수 생략
    public Program()
    {
      // 프로퍼티를 통해 맴버 변수 설정
      this.Data = 10;
    }
    // 프로퍼티
    public int Data
    {
      // 맴버 변수가 생략됨으로 get, set을 아래와 같이 설정할 수 있습니다. (컴파일 내부적으로는 변수가 있습니다.)
      // get, set의 특별한 제어식을 넣으려면 맴버 변수를 선언해야 합니다.
      get; protected set;
    }

    // 실행 함수
    public static void Main(string[] args)
    {
      // 인스턴스 생성
      Program p = new Program();
      // Program 인스턴스의 맴버 변수를 취득해 콘솔 출력
      Console.WriteLine("p - data = " + p.Data);

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

위에서 data의 맴버 변수를 생략해 버렸습니다. 그리고 프로퍼티에 보면 Static 영역을 생략하고 get; set;만 사용했습니다. set은 접근 제한자 설정도 했습니다.

프로퍼티만 사용한다고 맴버 변수가 없는 건 아닙니다. Class의 Reflection을 확인해 보면 변수가 있는 것을 확인할 수 있습니다.

using System;
using System.Reflection;

namespace Example
{
  // 클래스
  class Program
  {
    // 맴버 변수 data의 프로퍼티
    public int Data
    {
      get; set;
    }

    // 실행 함수
    public static void Main(string[] args)
    {
      // 인스턴스 생성
      Program p = new Program();
      // Reflection으로 맴버 변수의 리스트를 취득
      foreach (var field in p.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))
      {
        // 콘솔 출력
        Console.WriteLine(field.Name);
      }

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadLine();
    }
  }
}

Program 클래스는 Data의 프로퍼티만 선언을 했는데도 맴버 변수가 있는 것으로 나옵니다.


여기까지 C#에서의 프로퍼티(Property)에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.