오늘은 프로퍼티에 대해서 배워보겠습니다.
기존에 C++을 공부를 했었고, 은닉성을 위해서는 public으로 필드 멤버를 선언하는 것이 아닌 private로 감추고
필요한 부분만 getter, setter를 구현해서 사용하라고 배웠습니다.
맞는 방법이지만 한 변수에 getter와 setter까지 하면 변수가 많아질수록 이 수 또한 엄청 많아지게 될 것입니다.
C#에서는 이러한 것들을 한 뭉치로 묶을 수 있는 프로퍼티를 제공합니다!
# 프로퍼티
class Program
{
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
}
age라는 것을 Age라는 프로퍼티로 제공하게 됩니다.
Program p = new Program();
p.Age = 5; // 쉬운 setter
Console.WriteLine(p.Age); // 쉬운 getter
위와 같은 방식으로 쉽게 쓰고 대입할 수 있습니다.
좀 더 만들어봅시다.
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 Program
{
static void Main()
{
BirthdayInfo birth = new BirthdayInfo();
birth.Name = "지코";
birth.Birthday = new DateTime(1992, 9, 14);
Console.WriteLine($"Name : {birth.Name}");
Console.WriteLine($"Birthday : {birth.Birthday.ToShortDateString()}");
Console.WriteLine($"Age : {birth.Age}");
}
}
}
# 자동 구현 프로퍼티 (Auto-Implemented-Property)
위의 프로퍼티도 매력적이지만 좀 더 줄일 수 있습니다.
class Program
{
private int age;
public int Age { get; set; }
}
이렇게 작성하면 단순히 age를 읽고 쓰는 기능이기 때문에, C# 컴파일러가 자동으로 프로퍼티를 구현해줍니다.
C# 7.0부터는 자동 구현 프로퍼티 선언과 동시에 초기화도 가능하게 지원합니다.
class Program
{
private int age;
public int Age { get; set; } = 10;
}
자동 구현 프로퍼티의 선언과 동시에 초기화하는 예제를 연습해봅시다.
using System;
namespace AutoImplementedProperty
{
class BirthdayInfo
{
public string Name { get; set; } = "UnKnown";
public DateTime Birthday { get; set; } = new DateTime(1, 1, 1);
public int Age
{
get
{
return new DateTime(DateTime.Now.Subtract(Birthday).Ticks).Year;
}
}
}
class Program
{
static void Main()
{
BirthdayInfo birth = new BirthdayInfo();
Console.WriteLine($"Name : {birth.Name}");
Console.WriteLine($"Birthday : {birth.Birthday.ToShortDateString()}");
Console.WriteLine($"Age : {birth.Age}");
birth.Name = "지코";
birth.Birthday = new DateTime(1992, 9, 14);
Console.WriteLine($"Name : {birth.Name}");
Console.WriteLine($"Birthday : {birth.Birthday.ToShortDateString()}");
Console.WriteLine($"Age : {birth.Age}");
}
}
}
# 자동 구현 프로퍼티의 뒷단
자동 구현 프로퍼티가 우리에게 편리함을 가져줍니다.
class Program
{
//private int age; 이걸 쓰지 않아도 알아서 컴파일러가 뒷단에서 구현해줍니다.
public int Age { get; set; } = 10;
}
기존에는 private로 age를 만들고 앞에 Age로 프로퍼티를 지원했지만, 그냥 Age 프로퍼티만 선언한다면 C# 컴파일러가 자동으로 구현해줍니다. 이것 때문에 우리는 좀 더 편안한 프로그래밍이 가능해집니다.
# 프로퍼티와 생성자
기존에 클래스는 클래스를 생성하면서 안에 멤버 필드를 초기화하고 싶다면 생성자를 만들어서 사용했습니다. 그런데 프로퍼티가 등장으로 객체를 생성할 때 각 필드를 초기화하는 또 다른 방법이 있습니다.
Name과 Birthday는 각각의 string과 DateTime의 프로퍼티입니다.
객체를 생성할 때 각각의 프로퍼티를 초기화하는 과정입니다.
초기화하고 싶은 프로퍼티만 사용할 수 있습니다.
BirthdayInfo birth = new BirthdayInfo()
{
Name = "지코",
Birthday = new DateTime(1992, 9, 14)
};
using System;
namespace ConstructorWithProperty
{
class BirthdayInfo
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
public int Age
{
get
{
return new DateTime(DateTime.Now.Subtract(Birthday).Ticks).Year;
}
}
}
class Program
{
static void Main()
{
BirthdayInfo birth = new BirthdayInfo()
{
Name = "지코",
Birthday = new DateTime(1992, 9, 14)
};
Console.WriteLine($"Name : {birth.Name}");
Console.WriteLine($"Birthday : {birth.Birthday.ToShortDateString()}");
Console.WriteLine($"Age : {birth.Age}");
}
}
}
# 초기화 전용(Init-Only) 자동 구현 프로퍼티
기존에 초기화한 필드를 다시 바꾸려는 것을 막는 키워드가 있었습니다.
예를 들어서 readonly처럼 한 번 초기화하면 다음 변경을 막아버리는 키워드가 그 예시입니다.
프로퍼티도 이러한 기능을 지원합니다.
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}";
}
}
init 접근자는 set 접근자처럼 외부에서 프로퍼티 변경할 수 있지만 객체를 초기화할 때만 프로퍼티 변경이 가능하다는 점입니다. 이렇게 선언한 프로퍼티를 초기화 전용 자동 구현 프로퍼티라고 합니다.
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 Program
{
static void Main()
{
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);
}
}
}
각 트랜잭션은 객체를 생성할 때 각 프로퍼티를 초기화하고, 그 이후부터는 읽기 전용으로 사용하고 있습니다.
오늘은 프로퍼티가 왜 나오게 됐는지, 어떻게 사용하는지에 대해서 배웠습니다.
'CS > C#' 카테고리의 다른 글
[C#] 무명 형식, 인터페이스와 프로퍼티, 추상 클래스의 프로퍼티 (0) | 2021.12.21 |
---|---|
[C#] Record 와 Property (0) | 2021.12.21 |
[C#] 인터페이스와 추상 클래스 (0) | 2021.12.20 |
[C#] 정적 필드와 메서드(static) (0) | 2021.12.12 |
[C#] 생성자와 소멸자 (0) | 2021.12.11 |