C#
최신 C# 기능
C# 13
C# 최신 기능
C# 13: params modifier 지원 확장
C# 13: lock 지시어 향상
C# 13: \e (새 Escape Sequence)
C# 13: 객체 초기화 식에 ^ 연산자 사용
C# 13: ref struct 타입 기능 향상
C# 13: partial 속성과 인덱서
C# 13: OverloadResolutionPriority
C# 12
C# 12: 클래스 Primary Constructor
C# 12: 컬렉션 식
C# 12: ref readonly 파라미터 (in)
C# 12: 람다식 디폴트 파라미터
C# 12: InlineArray 특성
C# 12: using alias 모든 타입
C# 12: Experimental, Interceptor
C# 11
C# 11: Raw String Literal
C# 11: 문자열 내삽 복수라인
C# 11: u8 접미어
C# 11: Generic Math 지원
C# 11: Generic Attribute
C# 11: 리스트 패턴
C# 11: 파일 로컬 타입
C# 11: required modifier
C# 11: Auto-default struct
C# 11: ReadOnlySpan 패턴 매칭
C# 11: 확장된 nameof 범위
C# 11: nint, nuint
C# 11: ref 필드
C# 11: 소문자 타입명 경고
C# 11: 향상된 method group 변환
C# 10
VS 2022 설치
C# 10 global using
C# 10 File-scoped Namespace
C# 10 향상된 문자열 내삽
C# 10 향상된 람다식 유추
C# 10 struct 기능 향상
C# 10 record struct
C# 10 확장된 속성패턴
C# 10 향상된 명료한 할당
C# 10 Destructor 기능 개선
C# 9.0
C# 9 레코드 타입
C# 9 init accessor
C# 9 최상위 프로그램
C# 9 향상된 패턴 매칭
C# 9 향상된 Target Typing
C# 9 공변 리턴 타입
C# 9 Native Int 타입
C# 8.0
C# 8 디폴트 인터페이스 멤버
C# 8 패턴 매칭
C# 8 Nullable Reference Type
C# 8 인덱싱과 슬라이싱
C# 8 비동기 스트림
C# 8 using 선언
C# 8 널 병합 할당자
C# 8 구조체 읽기 전용 멤버
C# 8 기타 기능들
C# 7.0
C# 7.0 새기능
C# 7.0 패턴 매칭
C# 7.0 튜플
C# 7.0 로컬 함수
C# 7.0 out 파라미터
C# 7.0 리터럴 표현
C# 7.0 Deconstructor
C# 7.0 ref return
C# 7.0 async 리턴타입
C# 7.0 Expression-bodied
C# 7.0 throw expression
C# 6.0
C# 6.0 새기능
C# 6.0 널 조건 연산자
C# 6.0 문자열 내삽
C# 6.0 Dictionary초기자
C# 6.0 nameof 연산자
C# 6.0 using static문
C# 6.0 catch블럭 await
C# 6.0 Exception 필터
C# 6.0 자동 속성 초기자
C# 6.0 읽기전용 자동 속성
C# 6.0 Expression-bodied

C#으로 이해하는 자료구조
C# 프로그래밍 기초 실습 전자책
C# 13: ref struct 타입에 대한 기능 향상

C# 13에서부터 async 메서드 안에서 ref 로컬이나 ref struct 로컬 선언이 가능해졌다. 단, await 또는 yield 경계를 넘어서 엑세스하면, 컴파일러가 메모리 안전성을 위해 오류를 발생시킨다.

아래 예제의 MyAsync 메서드에서는 정수형의 ReadOnlySpan변수 span이 ref struct 로컬 변수로 선언되어 있다. span을 await 이전에 사용하면 문제가 없으나, ErrorAsync 메서드에서 처럼 await 이후에 사용하면 컴파일러가 오류를 발생한다.


예제

public static void Main()
{
    MyAsync(new int[] { 1, 2, 3 }).Wait();
}

static async Task<int> MyAsync(ReadOnlyMemory<int> mem)
{
    ReadOnlySpan<int> span = mem.Span; // ref struct 로컬
    int first = span[0];

    await Task.Delay(1);

    return first;
}

/* ERROR 
static async Task<int> ErrorAsync(ReadOnlyMemory<int> mem)
{
    ReadOnlySpan<int> span = mem.Span; // ref struct 로컬
    int first = span[0];

    await Task.Delay(1);

    // span을 여기서 다시 쓰면(경계 넘어) 컴파일러가 에러 발생
    // CS4007 Error: Instance of type 'System.ReadOnlySpan<int>' cannot be preserved across 'await' or 'yield' boundary.
    int res = span[0];
    return res;
} */




제네릭에서 ref struct 타입 인자 허용

C# 13에서 제네릭 타입(혹은 메서드)의 타입 파라미터에 anti-constraint 인 allows ref struct를 붙이면, ref struct를 타입 파라미터로 받을 수 있게 되었다.

아래 예제에서 Box 클래스는 T 타입 파라미터에 allows ref struct 제약 조건이 붙어서, ReadOnlySpan<char> 등과 같은 ref struct 타입을 타입 파라미터로 받을 수 있다. ref struct 타입은 스택에만 존재해야 하는 타입인데, 이걸 잘못해서 힙으로 흘려보내면 (예: 필드로 저장, 리턴으로 반환, async 캡처) 메모리 안전 문제가 발생한다. 이에 scoped 라는 C# 11 키워드를 붙여 ref struct 타입을 그 메서드 안에서 사용하는 것을 명시하였다.


예제


// 제네릭 타입파라미터 T로 ref struct 타입도 허용하는 Box 클래스
public sealed class Box<T> where T : allows ref struct
{
    // value는 ref struct 타입일 수 있으므로,
    // scoped (C# 키워드)를 사용하여 이 메서드 안에서만
    // 사용함을 컴파일러에게 명시함
    public void Use(scoped T value)
    {        
        if (value is ReadOnlySpan<char> span)
        {
            for (int i = 0; i < span.Length; i++)
            {
                Console.Write(span[i]);
            }
        }
    }
}



본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.