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 |
댓글