C#

프로퍼티

Barbarian developer 2024. 11. 1.

1. 프로퍼티의 개념

프로퍼티는 기본적으로 필드의 값을 읽고 쓰는 데 사용되는 접근자(getter와 setter)의 집합이입니다.

 

이 접근자를 통해 외부에서 직접적으로 필드에 접근하는 것이 아니라, 프로퍼티를 통해 값의 읽기(read)와 쓰기(write) 작업이 이루어집니다.

 

2. 프로퍼티의 구조

프로퍼티는 다음과 같은 두 가지 주요 구성 요소를 가진다:

  • get 접근자: 필드의 값을 반환한다. 값을 읽는 용도로 사용된다.
  • set 접근자: 필드에 값을 할당한다. 값을 변경하거나 설정할 때 사용된다.
public class Example
{
    private int number; // 실제 값을 저장할 필드

    // 프로퍼티 정의
    public int Number
    {
        get { return number; } // 값 읽기
        set { number = value; } // 값 쓰기
    }
}

 

using System;

namespace Property
{
    class BirthdayInfo
    {
        private string name;
        private DateTime birthday;

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public DateTime Birthday
        {
            get
            {
                return birthday;
            }
            set
            {
                birthday = value;
            }
        }

        public int Age
        {
            get
            {
                return new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year;
            }
        }
        
    }

    class MainApp
    {
        static void Main(string[] args)
        {
            BirthdayInfo birth = new BirthdayInfo();
            birth.Name = "서현";
            birth.Birthday = new DateTime(1991, 6, 28);

            Console.WriteLine("Name : {0}", birth.Name);
            Console.WriteLine("Birthday : {0}", birth.Birthday.ToShortDateString());
            Console.WriteLine("Age : {0}", birth.Age);
        }
    }
}

 

<실행결과>

 

자동구현 프로퍼티

자동 구현 프로퍼티는 C#에서 프로퍼티를 좀 더 간단하게 정의할 수 있는 방법이다. get과 set 접근자만으로 필드를 암묵적으로 생성할 수 있다. 이는 코드를 간결하게 하고, 프로퍼티의 기본 동작이 필드를 단순히 읽고 쓰는 것일 때 사용된다

public class Person
{
    public string Name { get; set; } // 자동 구현 프로퍼티
    public int Age { get; set; } = 0; // 기본값 설정도 가능
}
using System;

namespace AutoImplementedProperty
{
    // BirthdayInfo 클래스는 자동 구현 속성을 사용하여 개인 정보를 저장합니다.
    class BirthdayInfo
    {
        // Name 속성은 기본값으로 "Unknown"을 설정합니다.
        public string Name { get; set; } = "Unknown";

        // Birthday 속성은 기본값으로 날짜를 최소 날짜로 설정합니다.
        public DateTime Birthday { get; set; } = new DateTime(1, 1, 1);

        // Age 속성은 읽기 전용으로 현재 날짜와 Birthday 속성의 차이를 계산하여 연도를 반환합니다.
        public int Age
        {
            get
            {
                // 현재 날짜에서 Birthday를 뺀 Ticks를 이용하여 Age를 계산하고 연도로 반환합니다.
                return new DateTime(DateTime.Now.Subtract(Birthday).Ticks).Year;
            }
        }
    }

    // 프로그램의 메인 클래스
    class MainApp
    {
        static void Main(string[] args)
        {
            // BirthdayInfo 클래스의 객체 생성
            BirthdayInfo birth = new BirthdayInfo();

            // 기본값 출력
            Console.WriteLine($"Name : {birth.Name}"); // "Unknown"
            Console.WriteLine($"Birthday : {birth.Birthday.ToShortDateString()}"); // "1/1/0001"
            Console.WriteLine($"Age : {birth.Age}"); // 현재 날짜 기준 계산된 나이 (주로 1 또는 0)

            // 속성 값 설정
            birth.Name = "서현";
            birth.Birthday = new DateTime(1991, 6, 28); // 새로운 생일 설정

            // 변경된 값 출력
            Console.WriteLine($"Name : {birth.Name}"); // "서현"
            Console.WriteLine($"Birthday : {birth.Birthday.ToShortDateString()}"); // "6/28/1991"
            Console.WriteLine($"Age : {birth.Age}"); // 현재 날짜 기준으로 계산된 나이 출력
        }
    }
}

 

<실행결과>

 

프로퍼티와 생성자

4. 프로퍼티의 장점

프로퍼티를 사용함으로써 다음과 같은 장점을 얻을 수 있다:

  • 데이터 보호: set 접근자에 논리나 조건을 추가하여 잘못된 데이터가 할당되는 것을 방지할 수 있다.
  • 유연성: 클래스의 내부 구현은 변경하더라도 외부 코드에서의 접근 방식은 변경되지 않으므로 코드의 유연성을 유지할 수 있다.
  • 캡슐화 유지: 필드의 직접 접근을 막고, get과 set을 통해 캡슐화의 원칙을 따를 수 있다.

5. 사용 예시

실제 사용 사례로, 나이(Age)를 설정할 때 특정 조건을 적용하여 잘못된 값이 입력되지 않도록 set 접근자에 조건을 추가할 수 있다:

 
public class Student
{
    private int age;

    public int Age
    {
        get { return age; }
        set
        {
            if (value < 0 || value > 120)
                throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
            age = value;
        }
    }
}

 

6. 읽기 전용 및 쓰기 전용 프로퍼티

프로퍼티는 get과 set 접근자를 각각 선택적으로 사용할 수 있다. get만 제공하여 읽기 전용 프로퍼티를 만들 수 있으며, set만 제공하여 쓰기 전용 프로퍼티를 만들 수도 있다:

 

public class Book
{
    private string title;

    // 읽기 전용 프로퍼티
    public string Title
    {
        get { return title; }
    }

    // 생성자를 통해 설정
    public Book(string title)
    {
        this.title = title;
    }
}

 

7. 계산된 프로퍼티

계산된 프로퍼티는 필드를 직접 저장하지 않고, 다른 속성이나 메서드를 기반으로 값을 계산하여 반환한다. 예를 들어, 현재 연도와 생년을 기반으로 나이를 계산할 수 있다:

public class Person
{
    public DateTime BirthYear { get; set; }

    public int Age
    {
        get
        {
            return DateTime.Now.Year - BirthYear.Year;
        }
    }
}

 

8.초기화 전용 자동 구현 프로퍼티

set 접근자 대신 init 접근자를 사용.

 

초기화가 한차례 이뤄진 후 변경하면 안되는 데이터를 사용할 때, 사용함. 성적표, 범죄기록, 각종 국가 기록 등. 

using System;

namespace InitOnly
{
    class Transaction
    {
        public string From {get; init;}
        public string To {get; init;}
        public int Amount {get; init;}

        public override string ToString()
        {
            return $"{From,-10} -> {To,-10} : ${Amount}";
        }
    }

    class MainApp
    {
        static void Main(string[] args)
        {
            Transaction tr1 = new Transaction{From="Alice", To="Bob", Amount=100};
            Transaction tr2 = new Transaction{From="Bob", To="Charlie", Amount=50};
            Transaction tr3 = new Transaction{From="Charlie", To="Alice", Amount=50};

            Console.WriteLine(tr1);
            Console.WriteLine(tr2);
            Console.WriteLine(tr3);
        }
    }
}

 

<실행결과>

 

9.프로퍼티 초기화를 강제하는 required 키워드

init 접근자가 프로퍼티를 객체 초기화 시에만 값을 할당할 수 있도록 한다면, required는 초기화가 필요한 프로퍼티를 실수로 초기화하지 않는 실수를 방지해숩니다.

 

10. 무명 프로퍼티

 

무명 형식은형식의 선언과동시에 인스턴스를할당합니다.

이 때문에 인스턴스를만들고 다시는사용하지 않을 때 무명 형식이 요긴합니다.

(두 개 이상의 인스턴스를 만들려면 class나 strnct를 이용 해 이름을가진 형식을별도로만들어야겠죠).

using System;

namespace AnonymousType
{
    class MainApp
    {
        static void Main(string[] args)
        {
            var a = new { Name = "박상현", Age = 123 };
            Console.WriteLine("Name:{0}, Age:{1}", a.Name, a.Age);

            var b = new { Subject = "수학", Scores = new int[] { 90, 80, 70, 60 } };

            Console.Write("Subject:{0}, Scores: ", b.Subject);
            foreach (var score in b.Scores)
                Console.Write("{0} ", score);

            Console.WriteLine();
        }
    }
}

 

<실행결과>

 

11.추상 클래스의 프로퍼티

using System;

namespace PropertiesInAbstractClass
{
    abstract class Product
    {
        private static int serial = 0;
        public string SerialID
        {
            get { return String.Format("{0:d5}", serial++); }
        }

        abstract public DateTime ProductDate
        {
            get;
            set;
        }
    }

    class MyProduct : Product
    {
        public override DateTime ProductDate
        {
            get;
            set;
        }
    }

    class MainApp
    {
        static void Main(string[] args)
        {
            Product product_1 = new MyProduct()
            { ProductDate = new DateTime(2010, 1, 10) };

            Console.WriteLine("Product:{0}, Product Date :{1}",
                product_1.SerialID,
                product_1.ProductDate);

            Product product_2 = new MyProduct()
            { ProductDate = new DateTime(2010, 2, 3) };

            Console.WriteLine("Product:{0}, Product Date :{1}",
                product_2.SerialID,
                product_2.ProductDate);
        }
    }
}

 

<실행결과>

 

'C#' 카테고리의 다른 글

프로그래밍  (0) 2024.11.01
배열과 컬렉션 그리고 인덱서  (0) 2024.11.01
인터페이스와 추상클래스  (0) 2024.10.31
클래스  (0) 2024.10.30
메소드로 코드 간추리기  (0) 2024.10.30

댓글