C# 10 - (5) 속성 패턴의 개선
C# 8.0에 속성 패턴(책의 경우 852페이지 16.7.2 속성 패턴)의 지원이 추가되었는데요.
아래의 예는, 속성 패턴을 is 구문에 사용한 예를 보여줍니다.
Person p1 = new(new Name("Anders", "Hejlsberg"), 60);
Person p2 = new(new Name("Kevin", "Arnold"), 15);
Person p3 = new(new Name("Frank", "Arnold"), 15);
Person [] people = new Person[] { p1, p2, p3 };
foreach (Person p in people)
{
if (p is { Age: <= 20 } young)
{
Console.WriteLine($"{nameof(young)}: {young}");
}
}
record class Name(string Firstname, string LastName);
record class Person(Name Name, int Age);
/* 출력 결과
young: Person { Name = Name { Firstname = Kevin, LastName = Arnold }, Age = 15 }
young: Person { Name = Name { Firstname = Frank, LastName = Arnold }, Age = 15 }
*/
그리고, 위의 경우 만약 LastName == "Arnold"를 찾고 싶다면 이렇게 is 속성 패턴을 변경할 수 있습니다.
if (p is { Name: { LastName: "Arnold" } } arnold)
{
Console.WriteLine(arnold);
}
속성이 중첩되면서 저렇게 패턴이 적용된 것인데, 이런 불편함을 C# 10부터 개선해 점(.)으로 중첩 속성을 표현할 수 있습니다.
if (p is { Name.LastName: "Arnold" } arnold)
{
Console.WriteLine(arnold);
}
재미있는 것은, 해당 속성이 참조 타입인 경우 의미상으로 다음과 같이 해석을 하는 것과 같습니다.
// 의미상 그렇다는 것일 뿐, "?." 널 조건 연산자를 명시하면 컴파일 오류 발생: error CS8918: Identifier or a simple member access expected.
if (p is { Name?.LastName: "Arnold" } arnold)
{
Console.WriteLine(arnold);
}
실제로 다음의 코드는 null 참조 예외를 발생시키지 않습니다.
// ...[생략]...
Person p4 = new(null, 18);
Person [] people = new Person[] { p1, p2, p3, p4 };
foreach (Person p in people)
{
// Name 속성이 null인 경우 조건문은 false로 평가
if (p is { Name.LastName: "Arnold" } arnold)
{
Console.WriteLine(arnold);
}
}
참고로, 속성의 null 판단을 하고 싶다면 다음의 방법을 사용할 수 있습니다.
// 아래의 코드는 Name 속성이 참조 형식인 경우에만 가능
if (p is { Name : null } ) // p.Name == null
{
Console.WriteLine("p.Name is null");
}
// 아래의 코드는 Name 속성이 값 형식인 경우에도 허용, 물론 값 형식인 경우에는 언제나 true로 평가
if (p is { Name: { } }) // p.Name != null
{
Console.WriteLine("p.Name is not null");
}
당연히, 위의 코드들은 모두 switch 구문에도 적용 가능합니다.
(
첨부 파일은 이 글의 예제 코드를 포함합니다.)
C# 10 - (1) 구조체를 생성하는 record struct (공식 문서, Static Abstract Members In Interfaces C# 10 Preview)
; https://www.sysnet.pe.kr/2/0/12790
C# 10 - (2) 전역 네임스페이스 선언 (공식 문서, Global Using Directive)
; https://www.sysnet.pe.kr/2/0/12792
C# 10 - (3) 개선된 변수 초기화 판정 (공식 문서, Improved Definite Assignment)
; https://www.sysnet.pe.kr/2/0/12793
C# 10 - (4) 상수 문자열에 포맷 식 사용 가능 (공식 문서, Constant Interpolated Strings)
; https://www.sysnet.pe.kr/2/0/12796
C# 10 - (5) 속성 패턴의 개선 (공식 문서, Extended property patterns)
; https://www.sysnet.pe.kr/2/0/12799
C# 10 - (6) record class 타입의 ToString 메서드를 sealed 처리 허용 (공식 문서, Sealed record ToString)
; https://www.sysnet.pe.kr/2/0/12801
C# 10 - (7) Source Generator V2 APIs (Source Generator V2 APIs)
; https://www.sysnet.pe.kr/2/0/12804
C# 10 - (8) 분해 구문에서 기존 변수의 재사용 가능 (공식 문서, Mix declarations and variables in deconstruction)
; https://www.sysnet.pe.kr/2/0/12805
C# 10 - (9) 비동기 메서드가 사용할 AsyncMethodBuilder 선택 가능 (공식 문서, Async method builder override);
; https://www.sysnet.pe.kr/2/0/12807
C# 10 - (10) 개선된 #line 지시자 (공식 문서, Enhanced #line directive)
; https://www.sysnet.pe.kr/2/0/12812
C# 10 - (11) Lambda 개선 (공식 문서 1, 공식 문서 2, Lambda improvements)
; https://www.sysnet.pe.kr/2/0/12813
C# 10 - (12) 문자열 보간 성능 개선 (공식 문서, Interpolated string improvements)
; https://www.sysnet.pe.kr/2/0/12826
C# 10 - (13) 단일 파일 내에 적용되는 namespace 선언 (공식 문서, File-scoped namespace)
; https://www.sysnet.pe.kr/2/0/12828
C# 10 - (14) 구조체 타입에 기본 생성자 정의 가능 (공식 문서, Parameterless struct constructors)
; https://www.sysnet.pe.kr/2/0/12829
C# 10 - (15) CallerArgumentExpression 특성 추가 (공식 문서, Caller expression attribute)
; https://www.sysnet.pe.kr/2/0/12835
Language Feature Status
; https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]