<레코드 형식으로 만드는 불변 객체>
불변 객체는 내부 상태(데이터)를 변경할 수 없는 객체를 말한다
상태를 변경할 수 없다는 특성 때문에 불변 객체에서는 데이터 복사와 비교가 많이 이루어진다
레코드는 이 불변 객체에서 빈번하게 이뤄지는 이 두가지 연산을 편리하게 수행할 수 있도록 도입된 형식이다
record Transaction
{
public string From { get; init; }
public string To { get; init; }
public int Amount { get; init; }
}
우선 레코드는 이렇게 선언하고 이렇게 선언된 레코드로 인스턴스를 만들면 불변 객체가 만들어진다
Transaction tr1 = new Transaction { From = "Alice", To = "Bob", Amount = 100 };
Transaction tr2 = new Transaction { From = "Bob", To = "Tom", Amount = 50 };
<with을 이용한 레코드 복사와 수정>
Transaction tr1 = new Transaction { From = "Alice", To = "Bob", Amount = 100 };
Transaction tr2 = with tr1 { From = "charlie" };
이렇게 하면 tr1의 상태를 복사한뒤 tr2에 새로 생성해주고 From 값만 charlie로 변경해주는 것이다
<무명 형식>
C#에는 int, string, double 같은 형식등이 있다
하지만 이번에는 이름이 없는 형식, 즉 무명형식에 대해 알아보자
int a
double b
string 형식이름
형식에는 왜 이름이 필요할까? 위와 같이 형식의 이름을 이용하여 인스턴스를 만들기 때문이다
하지만 무명 형식은 형식의 선언과 동시에 인스턴스를 할당한다
이 때문에 인스턴스를 만들고 나서 다시는 사용하지 않을때 무명형식이 요긴하게 사용된다고 한다
var myinstance = new { Name = "박상현", Age = 17 };
---------------------------------------------------
Console.WriteLine(myinstance.Name, myinstance.Age); // 박상현, 17
무명형식을 선언하고 사용하는 예이다.
여기서 주의할 점이 있다면 무명형식의 프로퍼티에 할당된 값은 변경이 불가능하다는 사실이다. 읽기만 가능하다
class MainApp
{
static void Main(string[] args)
{
var a = new { Name = "박상혁", Age = 123};
var b = new { Subject = "수학", Score = new int[] { 10, 20, 30, 40, 50 } };
Console.WriteLine($"{a.Name}, {a.Age}"); // 박상혁 123
Console.WriteLine($"{b.Subject}, {b.Score[0]}"); // 수학 10
}
}
예시 코드이다
<인터페이스의 프로퍼티>
인터페이스의 개념과 상속, 추상클래스
interface 인터페이스 이름{ 반환형식 메서드이름(매개변수들); 반환형식 메서드이름(매개변수들); 반환형식 메서드이름(매개변수들);} 우선 인터페이스는 이런 형식으로 interface 키워드를 이용해
sangeun00.tistory.com
프로퍼티
class MainApp{ private int myfield;} 다음과 같은 클래스가 있다고 가정해보자.이 클래스는 int 타입 myfield를 private로 갖고 있다 그럼 이걸 메인 메서드에서 사용하려면 어떻게 해야할까?private로 선언되어
sangeun00.tistory.com
위 두개의 글에서 파생된 내용이기도 한 인터페이스의 프로퍼티. 말 그대로 인터페이스는 프로퍼티를 가질 수 있다
interface 인터페이스이름
{
public 형식 프로퍼티이름
{
get;
set;
}
///
}
interface IProduct
{
string ProductName
{
get; set;
}
}
class Product : IProduct
{
private string ProductName;
public string ProductName // 파생클래스는 기반 인터페이스에 선언된 모든 프로퍼티를 구현한다
{
get { return ProductName };
set { ProductName = value};
}
}
이런식으로 선언이 가능하며 이제 예제코드를 보도록 하자
interface INamedValue
{
string Name
{
get; set;
}
string Value
{
get; set;
}
}
class NameValue : INamedValue
{
public string Name
{
get; set;
}
public string Value
{
get; set;
}
}
class MainApp
{
static void Main(string[] args)
{
NameValue name = new NameValue() { Name = "이름", Value = "박상현" };
NameValue height = new NameValue() { Name = "키", Value = "177cm" };
NameValue weight = new NameValue() { Name = "몸무게", Value = "90kg" };
Console.WriteLine($"{name.Name} : {name.Value}");
Console.WriteLine($"{height.Name} : {height.Value}");
Console.WriteLine($"{weight.Name} : {weight.Value}");
}
}
<추상클래스의 프로퍼티>
인터페이스를 했으니 추상클래스도 안해줄 수 없다
추상 클래스는 클래스처럼 구현된 프로퍼티를 가질 수 있는 반면, 인터페이스처럼 구현되지 않은 프로퍼티도 가질 수 있다
이것을 추상 프로퍼티라고 한다. 추상 프로퍼티 역시 인터페이스의 프로퍼티와 다를것이 없다
그렇다면 추상 프로퍼티는 어떻게 선언해야 할까?
인터페이스처럼 구현을 비워넣고 추상 프로퍼티를 만들 수 없다
C# 컴파일러가 자동 구현 프로퍼티로 간주하고 구현을 자동으로 채워넣을테니 말이다
그렇기에 추상 프로퍼티는 다음과 같이 abstract 한정자를 이용해서 선언한다
abstract class 추상 클래스이름
{
abstract 데이터형식 프로퍼티이름
{
get; set
}
}
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(2018, 1, 10) };
Console.WriteLine("Produt : {0}, Product Date :{1}", product_1.SerialID, product_1.ProductDate);
Product product_2 = new MyProduct() { ProductDate = new DateTime(2018, 2, 23) };
Console.WriteLine("Produt : {0}, Product Date :{1}", product_2.SerialID, product_2.ProductDate);
}
}
'C# > 3. 프로퍼티 & 배열과 컬렉션,인덱서' 카테고리의 다른 글
프로퍼티 (1) | 2025.05.07 |
---|