레코드 형식으로 만드는 불변 객체
불변객체는 내부 상태(데이터)를 변경할 수 없는 객체 (앞에서도 많이 했던 readonly)
상태를 변경할 수 없다는 특성 때문에 불변 객체에서는 데이터 복사와 비교가 많이 이루어짐
새로운 상태를 복사한 뒤 이 중 일부를 수정해서 새로운 객체를 만들고 ,
상태를 확인하기 위해 객체 내용을 자주 비교한다
레코드는
불변 객체에서 이뤄지는 이 두 가지 연산을 편리하게 수행할 수 있도록 C# 9.0에 도입된 형식
앞에서 불변 객체를 만드는 방법이
참조 형식 : 클래스의 모든 필드를 readonly로 선언
값 형식 : readonly struct로 구조체를 선언
값 형식 객체는 다른 객체에 할당할 때 깊은 복사를 수행
(모든 필드를 새 객체가 가진 필드에 1:1로 복사)
필드가 많을 수록, 객체를 여러 곳에서 사용할 수록 복사 비용은 커짐
하지만
참조 형식은 이러한 오버헤드가 없다
객체가 참조하는 메모리 주소만 복사하면 되니까
하지만 프로그래머가 직접 깊은 복사를 구현해야 한다는 단점 존재
값 형식은 객체를 비교할 때 기본적으로 내용을 비교하는데 모든필드를 1:1로 비교한다고 했다
반면 참조형식은 프로그래머가 직접 비교 코드를 작성해야 하는데
보통은 object로부터 상속하는 Equals()메소드를 오버라이딩한다
불변 객체를 참조 형시으로 선언하면 함수 호출 인수나 컬렉션 요소로 사용할 때
복사 비용을 줄일 수 있다. 한편,
불변 객체는 값 형식으로 선언하는 편이 프로그래머에게 편리한 부분이 많다
레코드 형식은 값 형식처럼 다룰 수 있는 불변 참조 형식으로,
참조 형식의 비용 효율과 값 형식이 주는 편리함을 모두 제공
record RTransaction
{
public string From {get; init;}
public string to {get; init;}
public int Amount {get; init;}
}
레코드에는 초기화 전용 자동구현 프로퍼티(init) 뿐만 아니라 쓰기 가능한 프로퍼티와 필드도 자유롭게 선언해
너흘 수 있지만 여기선 초기화자동구현 프로퍼티(init)만을 이용해 상태를 표현함
RTransaction tr1 = new RTransaction{From = "Alice", To = "Bob", Amont = 100};
RTransaction tr2 = new RTransaction{From = "Bob", To = "Charlie", Amont = 300};
+ with을 이용한 레코드 복사 pg 340
RTransaction tr1 = new RTransaction{From = "Alice", To = "Bob", Amont = 100};
RTransaction tr2 = new RTransaction{From = "Bob", To = "Charlie", Amont = 300};
//tr1 의 모든 상태를 복사한 다음 To프로퍼티 값만 Charlie로 수정
+ 레코드 객체 비교
컴파일러는 레코드의 상태를 비교하는 Equals() 메소드를 자동으로 구현한다
클래스 | 레코드 |
|
|
클래스는 위에 비교함수 Equals()를 직접 작성해준 반면에
레코드는 값 형식처럼 Equals() 메소드를 구현하지 않아도 비교가 가능하다
//클래스
CTransaction trA = new CTransaction{From = "Alice" , To = "Bob", Amount = 100};
CTransaction trB = new CTransaction{From = "Alice", To = "Bob", Amount = 100};
Console.WriteLine(trA.Equals(trB)); //True 출력
//레코드
RTransaction tr1 = new RTransaction{From = "Alice", To = "Bob", Amount = 100};
RTransaction tr2 = new RTransaction{From = "Alice", To = "Bob", Amount = 100};
Console.WriteLine(tr1.Equals(tr2)); //True 출력
//클래스는 위에 비교함수 Equals()를 직접 작성해준 반면에
//레코드는 값 형식처럼 Equals() 메소드를 구현하지 않아도 비교가 가능하다
+ var 무명형식
- 무명형식은 선언과 동시에 인스턴스를 할당한다
- 이 때문에 인스턴스를 만들고 다시 사용하지 않을 때 무명형식이 요긴
- 무명 형식의 프로퍼티에 할당된 값은 변경불가능하다는 것을 주의 (만들어지고 난 다음은 읽기만 할 수 있다)
- 15장에서 배울 LINQ와 함께 사용하면 요긴하다
var myInstance = new { Name = "김지훈", Age = "24"};
Console.WriteLine(myInstance.Name, myInstance.Age);
+ 인터페이스의 프로퍼티
+ 추상클래스의 프로퍼티
레코드 형식으로 만드는 불변 객체
불변객체는 내부 상태(데이터)를 변경할 수 없는 객체 (앞에서도 많이 했던 readonly)
상태를 변경할 수 없다는 특성 때문에 불변 객체에서는 데이터 복사와 비교가 많이 이루어짐
새로운 상태를 복사한 뒤 이 중 일부를 수정해서 새로운 객체를 만들고 ,
상태를 확인하기 위해 객체 내용을 자주 비교한다
레코드는
불변 객체에서 이뤄지는 이 두 가지 연산을 편리하게 수행할 수 있도록 C# 9.0에 도입된 형식
앞에서 불변 객체를 만드는 방법이
참조 형식 : 클래스의 모든 필드를 readonly로 선언
값 형식 : readonly struct로 구조체를 선언
값 형식 객체는 다른 객체에 할당할 때 깊은 복사를 수행
(모든 필드를 새 객체가 가진 필드에 1:1로 복사)
필드가 많을 수록, 객체를 여러 곳에서 사용할 수록 복사 비용은 커짐
하지만
참조 형식은 이러한 오버헤드가 없다
객체가 참조하는 메모리 주소만 복사하면 되니까
하지만 프로그래머가 직접 깊은 복사를 구현해야 한다는 단점 존재
값 형식은 객체를 비교할 때 기본적으로 내용을 비교하는데 모든필드를 1:1로 비교한다고 했다
반면 참조형식은 프로그래머가 직접 비교 코드를 작성해야 하는데
보통은 object로부터 상속하는 Equals()메소드를 오버라이딩한다
불변 객체를 참조 형시으로 선언하면 함수 호출 인수나 컬렉션 요소로 사용할 때
복사 비용을 줄일 수 있다. 한편,
불변 객체는 값 형식으로 선언하는 편이 프로그래머에게 편리한 부분이 많다
레코드 형식은 값 형식처럼 다룰 수 있는 불변 참조 형식으로,
참조 형식의 비용 효율과 값 형식이 주는 편리함을 모두 제공
record RTransaction
{
public string From {get; init;}
public string to {get; init;}
public int Amount {get; init;}
}
레코드에는 초기화 전용 자동구현 프로퍼티(init) 뿐만 아니라 쓰기 가능한 프로퍼티와 필드도 자유롭게 선언해
너흘 수 있지만 여기선 초기화자동구현 프로퍼티(init)만을 이용해 상태를 표현함
RTransaction tr1 = new RTransaction{From = "Alice", To = "Bob", Amont = 100};
RTransaction tr2 = new RTransaction{From = "Bob", To = "Charlie", Amont = 300};
+ with을 이용한 레코드 복사 pg 340
RTransaction tr1 = new RTransaction{From = "Alice", To = "Bob", Amont = 100};
RTransaction tr2 = new RTransaction{From = "Bob", To = "Charlie", Amont = 300};
//tr1 의 모든 상태를 복사한 다음 To프로퍼티 값만 Charlie로 수정
+ 레코드 객체 비교
컴파일러는 레코드의 상태를 비교하는 Equals() 메소드를 자동으로 구현한다
클래스 | 레코드 |
|
|
클래스는 위에 비교함수 Equals()를 직접 작성해준 반면에
레코드는 값 형식처럼 Equals() 메소드를 구현하지 않아도 비교가 가능하다
//클래스
CTransaction trA = new CTransaction{From = "Alice" , To = "Bob", Amount = 100};
CTransaction trB = new CTransaction{From = "Alice", To = "Bob", Amount = 100};
Console.WriteLine(trA.Equals(trB)); //True 출력
//레코드
RTransaction tr1 = new RTransaction{From = "Alice", To = "Bob", Amount = 100};
RTransaction tr2 = new RTransaction{From = "Alice", To = "Bob", Amount = 100};
Console.WriteLine(tr1.Equals(tr2)); //True 출력
//클래스는 위에 비교함수 Equals()를 직접 작성해준 반면에
//레코드는 값 형식처럼 Equals() 메소드를 구현하지 않아도 비교가 가능하다
+ var 무명형식
- 무명형식은 선언과 동시에 인스턴스를 할당한다
- 이 때문에 인스턴스를 만들고 다시 사용하지 않을 때 무명형식이 요긴
- 무명 형식의 프로퍼티에 할당된 값은 변경불가능하다는 것을 주의 (만들어지고 난 다음은 읽기만 할 수 있다)
- 15장에서 배울 LINQ와 함께 사용하면 요긴하다
var myInstance = new { Name = "김지훈", Age = "24"};
Console.WriteLine(myInstance.Name, myInstance.Age);
+ 인터페이스의 프로퍼티
+ 추상클래스의 프로퍼티