이 글은 기계 번역의 미러 문서이며, 원본 기사로 바로 이동하려면 여기를 클릭해 주세요.

보기: 3341|회답: 0

[출처] .NET/C# 새로운 기능 레코드 유형

[링크 복사]
게시됨 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 메서드를 호출하는 것도 기록된 값을 출력하는 데 매우 직관적입니다. 아래에 나와 있습니다:

.NET/C#은 IEqualityComparer 맞춤형 비교기를 구현합니다
https://www.itsvse.com/thread-10643-1-1.html



기록

필수:required modifier는 적용되는 필드나 속성이 모든 생성자에 의해 초기화되거나 객체 초기화자를 사용해야 함을 나타냅니다. 해당 유형의 새로운 인스턴스를 초기화하는 데 사용되는 모든 표현식은 반드시 필요한 모든 멤버를 초기화해야 합니다.
참조:하이퍼링크 로그인이 보입니다.

이니: C# 9 이후 버전에서는 init 키워드가 속성이나 인덱서에서 accessor 메서드를 정의합니다. init-only 라이브러리는 객체 구성 시 속성이나 인덱서 요소에만 값을 할당합니다. 이로 인해 객체가 초기화되면 더 이상 변경할 수 없게 되어 불변성을 강제합니다.
참조:하이퍼링크 로그인이 보입니다.

: 수정을 거쳐 인스턴스를 복제해야 한다면, with 표현식을 사용해 비파괴적 변경을 구현할 수 있습니다. 표현식을 사용하여 기존 레코드 인스턴스의 복사본인 새 레코드 인스턴스를 생성하고, 지정된 속성과 필드를 수정합니다.
참조:하이퍼링크 로그인이 보입니다.

따라서 기록은 다음과 같이 정의할 수 있습니다:

필수, init, 그리고 실제로 구문 Sugar가 있으면자동으로 생성된 $ 메서드를 호출합니다 <Clone>그리고 속성의 값을 수정합니다. 다음과 같습니다:



코드:



레코드 속성

때로는 JSON 직렬화 기능, 설명 정보 등 속성을 추가해야 할 때도 있습니다.



리소스:

하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.





이전의:ASP.NET 코어(24)는 Refit, MemoryPack 고성능 통신을 기반으로 합니다
다음:GitHub는 REST API를 사용해 저장소 크기를 확인합니다
면책 조항:
Code Farmer Network에서 발행하는 모든 소프트웨어, 프로그래밍 자료 또는 기사는 학습 및 연구 목적으로만 사용됩니다; 위 내용은 상업적 또는 불법적인 목적으로 사용되지 않으며, 그렇지 않으면 모든 책임이 사용자에게 부담됩니다. 이 사이트의 정보는 인터넷에서 가져온 것이며, 저작권 분쟁은 이 사이트와는 관련이 없습니다. 위 내용은 다운로드 후 24시간 이내에 컴퓨터에서 완전히 삭제해야 합니다. 프로그램이 마음에 드신다면, 진짜 소프트웨어를 지원하고, 등록을 구매하며, 더 나은 진짜 서비스를 받아주세요. 침해가 있을 경우 이메일로 연락해 주시기 바랍니다.

Mail To:help@itsvse.com