|
|
게시됨 2023. 10. 2. 오전 9:25:51
|
|
|
|

C# 9부터는 레코드 수정자를 사용해 데이터를 캡슐화하는 내장 기능을 제공하는 참조 타입을 정의할 수 있습니다. C# 10은 참조 유형을 명확히 하기 위해 레코드 클래스 구문을 동의어로 사용할 수 있으며, 레코드 구조체가 동일한 기능을 사용하여 값 유형을 정의할 수 있게 합니다.
C#에서 기록을 위한 사용 사례(ChatGPT 답변):
C#의 레코드 타입은 최신 버전에서 도입된 새로운 기능입니다. 이 방법은 다음을 포함하되 이에 국한되지 않는 다양한 상황에서 사용할 수 있습니다:
변경 불가능한 데이터 객체: 레코드 유형은 변경 불가능하며, 일단 생성되면 속성 값을 변경할 수 없습니다. 이로 인해 전송 객체(DTO)나 구성 설정과 같은 불변 데이터 구조를 표현하는 데 이상적입니다. 가치 객체: 레코드 유형은 참조 동등성이 아닌 속성 값에 따라 동등하게 결정되는 값 객체를 나타내는 데 사용할 수 있습니다. 이로 인해 날짜 범위, 좌표점 등과 같은 값 객체를 비교하고 저장하는 데 이상적입니다. 패턴 매칭: 레코드 타입은 패턴 매칭과 함께 사용할 수 있어 복잡한 데이터 구조를 다룰 때 더 편리합니다. 패턴 매칭을 사용해 레코드 객체의 속성 값을 확인하고 추출하여 적절한 작업을 수행할 수 있습니다. 변경 불가능한 컬렉션: 레코드 유형은 ImmutableList, ImmutableDictionary 등과 같은 변경 가능한 컬렉션 유형과 함께 사용하여 변경 가능한 컬렉션 객체를 생성할 수 있습니다. 이로 인해 컬렉션의 내용이 변경되지 않아 코드의 신뢰성과 보안이 향상됩니다. 이것들은 레코드 유형의 사용 사례 중 일부에 불과하며, 본인의 구체적인 필요와 코드 구조에 따라 레코드 유형을 사용할지 결정할 수 있습니다. 레코드와 클래스, 구조체의 차이점
클래스나 구조를 선언하고 인스턴스화할 때 사용하는 구문은 연산을 기록할 때와 동일합니다. 클래스 키워드를 record로 바꾸거나, struct 대신 record struct를 사용하세요. 마찬가지로, 레코드 클래스는 상속 관계에 대해 동일한 문법을 지원합니다. 레코드와 클래스의 차이는 다음과 같습니다:
- 메인 컨스트럭터에서 위치 매개변수를 사용해 불변 속성을 가진 타입을 만들고 인스턴스화할 수 있습니다.
- 클래스 내 참조 동등 또는 비동등을 나타내는 방법과 연산자(예: Object.Equals(Object) 및 ==)는 레코드 내 값 동등 또는 비평등을 나타냅니다.
- with 표현식을 사용해 선택한 속성에 새로운 값을 가진 불변 객체의 복사본을 만들 수 있습니다.
- 레코드의 ToString 메서드는 객체의 타입 이름과 모든 공통 속성의 이름 및 값을 보여주는 형식 문자열을 생성합니다.
- 레코드는 다른 레코드에서 상속될 수 있습니다. 하지만 레코드는 클래스에서 상속될 수 없으며, 클래스는 레코드에서 상속될 수 없습니다.
- 레코드 구조와 구조의 차이점은 컴파일러가 등식과 ToString을 결정하기 위한 메서드를 종합한다는 점입니다. 컴파일러는 위치 레코드 구조에 대해 Deconstruct 메서드를 합성합니다.
컴파일러는 레코드 클래스 내 각 주요 생성자 매개변수에 대해 공통 초기화 전용 속성을 합성합니다. 레코드 구조체에서 컴파일러는 공개 읽기/쓰기 속성을 합성합니다. 컴파일러는 레코드 수정자가 없는 클래스 및 구조체 타입에서 메인 생성자 인자에 대한 속성을 생성하지 않습니다.
기록
레코드 클래스 참조 유형 (기본값: 클래스는 생략 가능) 레코드 구조 값 유형
레코드 문법 설탕
기록은 사실 그렇습니다구문 슈가, 그리고 최종 결과물은 클래스 또는 구조체 코드입니다。 다음 코드를 예로 들어보겠습니다:
마지막으로, 다음 코드로 컴파일됩니다:
System을 사용; System.Collections.Generic을 사용; System.Diagnostics를 사용; System.Reflection을 사용; System.Runtime.CompilerServices를 사용; System.Security를 사용; System.Security.Permissions를 사용; System.Text 사용; Microsoft.CodeAnalysis를 사용;
[어셈블리: 컴파일레이션이스(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [어셈블리: AssemblyVersion("0.0.0.0")] [모듈: 검증 불가능한 코드] [모듈: System.Runtime.CompilerServices.RefSafetyRules(11)]
[System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class PersonInfo : IEquatable<PersonInfo>
{ [컴파일러생성] [DebuggerBrowsable(DebuggerBrowsableState.Never)] 개인 읽기 문자열 <FirstName>k__BackingField;
[컴파일러생성] [DebuggerBrowsable(DebuggerBrowsableState.Never)] 개인 읽기 문자열 <LastName>k__BackingField;
[컴파일러생성] 보호된 가상 타입 평등계약 { [컴파일러생성] 가져오기 { return: typeof(PersonInfo); } }
공개 문자열 이름(FirstName) { [컴파일러생성] 가져오기 { k__BackingField 반환<FirstName>; } [컴파일러생성] 이니 { <FirstName>k__BackingField = 가치; } }
공개 문자열 성씨 { [컴파일러생성] 가져오기 { k__BackingField 반환<LastName>; } [컴파일러생성] 이니 { <LastName>k__BackingField = 가치; } }
public PersonInfo(이름 문자열, 성씨 문자열) { <FirstName>k__BackingField = 이름; <LastName>k__BackingField = 성; 기지.. ctor(); }
[컴파일러생성] 공개 오버라이드 문자열 ToString() { StringBuilder stringBuilder = 새로운 StringBuilder(); stringBuilder.Append("PersonInfo"); stringBuilder.Append(" { "); 만약 (PrintMembers(stringBuilder)) { stringBuilder.Append(' '); } stringBuilder.Append('}'); return stringBuilder.ToString(); }
[컴파일러생성] 보호된 가상 불 PrintMembers(StringBuilder 빌더) { RuntimeHelpers.EnsureSufficientExecutionStack(); 건설자. 덧붙임("FirstName = "); 건설자. Append((object)FirstName); 건설자. Append(", 성 = "); 건설자. Append((object)LastName); 진짜로 반환; }
[System.Runtime.CompilerServices.NullableContext(2)] [컴파일러생성] public static bool operator !=(PersonInfo 왼쪽, PersonInfo 오른쪽) { 돌아오다! (왼쪽 == 오른쪽); }
[System.Runtime.CompilerServices.NullableContext(2)] [컴파일러생성] public static bool operator ==(PersonInfo left, PersonInfo right) { return (object)left == 오른쪽 || ((object)left != null & left. 이른(오른쪽)); }
[컴파일러생성] 공개 오버라이드 int GetHashCode() { 반환 (EqualityComparer<Type>. Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<FirstName>k__BackingField)) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<LastName>k__BackingField); }
[System.Runtime.CompilerServices.NullableContext(2)] [컴파일러생성] public override bool Equals(object obj) { Equals(PersonInfo로 표현됨); }
[System.Runtime.CompilerServices.NullableContext(2)] [컴파일러생성] public virtual bool Equals(PersonInfo other) { return (object) this == 기타 || ((object)other != null & & EqualityContract == other. EqualityContract 및 & EqualityComparer<string>. Default.Equals(<FirstName>k__BackingField, 기타.<FirstName>k__BackingField) 및 EqualityComparer<string>. Default.Equals(<LastName>k__BackingField, 기타.<LastName>k__BackingField)); }
[컴파일러생성] 공개 가상 PersonInfo <Clone>$() { 새 PersonInfo(this); }
[컴파일러생성] 보호된 PersonInfo(원본 PersonInfo) { <FirstName>k__BackingField = 원본. <FirstName>k__BackingField; <LastName>k__BackingField = 원본. <LastName>k__BackingField; }
[컴파일러생성] 공공 공허 디스컨스트럭트(스트링 이름, 스트링 스트래닛 아웃) { FirstName = 이것. 이름; 성 = 이것. 성; }
}
네임스페이스, Microsoft.CodeAnalysis
{ [컴파일러생성] [삽입됨] 내부 밀봉 클래스 EmbeddedAttribute : Attribute { }
}
네임스페이스 System.Runtime.CompilerServices
{ [컴파일러생성] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | 속성 목표 | 속성 목표 필드 | 속성 목표 사건 | 속성 목표 매개변수 | 속성 목표.반환값 | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false) 내부 밀봉 클래스 NullableAttribute : 속성 { 공개 읽기 바이트[] NullableFlags;
public NullableAttribute(byte P_0) { 바이트[] 배열 = 새 바이트[1]; array[0] = P_0; NullableFlags = 배열; }
public NullableAttribute(바이트[] P_0) { NullableFlags = P_0; } }
[컴파일러생성] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | 속성 표적.구조체 | 속성 표적.메서드 | 속성 목표 인터페이스 | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false) 내부 실링 클래스 NullableContextAttribute : 속성 { 공개 읽기 바이트 플래그;
public NullableContextAttribute(바이트 P_0) { 깃발 = P_0; } }
[컴파일러생성] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] 내부 밀봉 클래스 RefSafetyRules속성 : 속성 { 공개 읽기 내역 버전;
공개 RefSafetyRulesAttribute(int P_0) { 버전 = P_0; } }
} 자동으로 구성자를 생성하고, ToString, GetHashCode, Equals 메서드를 다시 작성하며, 일부 메서드도 자동으로 생성합니다.
p1과 p2는 사실 서로 다른 두 객체이지만, 컴파일러가 자동으로 비교기(IEquatable)를 생성하고 Equals와 GetHashCode 메서드를 다시 작성했기 때문에 출력은 참이었습니다. ToString 메서드를 호출하는 것도 기록된 값을 출력하는 데 매우 직관적입니다. 아래에 나와 있습니다:
기록
필수:required modifier는 적용되는 필드나 속성이 모든 생성자에 의해 초기화되거나 객체 초기화자를 사용해야 함을 나타냅니다. 해당 유형의 새로운 인스턴스를 초기화하는 데 사용되는 모든 표현식은 반드시 필요한 모든 멤버를 초기화해야 합니다. 참조:하이퍼링크 로그인이 보입니다.
이니: C# 9 이후 버전에서는 init 키워드가 속성이나 인덱서에서 accessor 메서드를 정의합니다. init-only 라이브러리는 객체 구성 시 속성이나 인덱서 요소에만 값을 할당합니다. 이로 인해 객체가 초기화되면 더 이상 변경할 수 없게 되어 불변성을 강제합니다. 참조:하이퍼링크 로그인이 보입니다.
와: 수정을 거쳐 인스턴스를 복제해야 한다면, with 표현식을 사용해 비파괴적 변경을 구현할 수 있습니다. 표현식을 사용하여 기존 레코드 인스턴스의 복사본인 새 레코드 인스턴스를 생성하고, 지정된 속성과 필드를 수정합니다. 참조:하이퍼링크 로그인이 보입니다.
따라서 기록은 다음과 같이 정의할 수 있습니다:
필수, init, 그리고 실제로 구문 Sugar가 있으면자동으로 생성된 $ 메서드를 호출합니다 <Clone>그리고 속성의 값을 수정합니다. 다음과 같습니다:
코드:
레코드 속성
때로는 JSON 직렬화 기능, 설명 정보 등 속성을 추가해야 할 때도 있습니다.
리소스:
하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.
|
이전의:ASP.NET 코어(24)는 Refit, MemoryPack 고성능 통신을 기반으로 합니다다음:GitHub는 REST API를 사용해 저장소 크기를 확인합니다
|