C#
최신 C# 기능
C# 11
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# 7 : async 커스텀 리턴 타입

지금까지의 async / await는 void, Task, Task<T> 등 3가지 리턴 타입만을 가질 수 있었는데, Task는 리턴값이 없는 비동기 메서드를 위해서 사용되었고, Task<T>는 리턴값 T를 갖는 비동기 메서드를 위해 사용되었다. void는 주로 이벤트핸들러를 위해 사용되었지만 메서드 내부에서 Unhandled Exception이 발생하면 프로세스를 다운시키는 문제가 있어서 사용을 자제한 리턴타입이다.

C# 7 에서는 이러한 3가지 async 리턴타입에 대한 제약을 넘어 커스텀 리턴 타입을 허용하게 되었는데, 이러한 커스텀 타입은 async 패턴에 맞게 정의되어야 한다. 이러한 Custom 리턴 타입의 하나로 .NET Framework에서 ValueTask<T> 라는 타입이 제공되고 있는데, 필요한 경우 Nuget 패키지에서 System.Threading.Tasks.Extensions 을 설치하여 사용한다.




C# 7 : ValueTask<T>

async 메서드에서 흔히 사용하는 Task, Task<T> 리턴타입은 비동기 처리가 필요없이 상수값을 리턴할 때도 Task 객체를 항상 만들기 때문에 일부 경우에 성능을 저하시킬 수 있다.

ValueTask<T> 타입은 값 T 와 Task<T> 가 결합된 형태라고 볼 수 있는데, async 메서드 내에서 동기 처리가 필요할 때는 Task 객체를 생성하지 않고 직접 값 T 를 리턴하고, 비동기 처리가 필요할 때는 Task 객체를 생성하여 사용하게 된다. 따라서, ValueTask<T> 타입은 async 메서드 내에 동기 처리와 비동기 처리가 혼합되어 있을 때 유용하다.

예를 들어, async 메서드가 캐쉬에 데이타가 있으면 즉시 동기적으로 캐쉬값을 리턴하고 그렇지 않으면 네트워크을 통해 비동기적으로 값을 가져와야 하는 경우, async 리턴타입으로 ValueTask<T>을 사용하면 성능 향상을 기대할 수 있다.
아래 예제는 캐쉬를 사용하여 동기와 비동기 처리를 함께 수행하는 async 메서드에 대한 예로서 리턴타입으로 ValueTask<T> 커스텀 타입을 사용하고 있다. (여기서 ValueTask 대신 Task를 써도 동작하지만 ValueTask이 더 효율적이다)


예제

private Dictionary<int, int> cache = new Dictionary<int, int>();

private async ValueTask<int> GetCache(int id)
{
    if (cache.ContainsKey(id))
    {
        // 동기 처리. 값 직접 리턴
        return cache[id];
    }
    else
    {
        // 비동기 처리. Task 객체 생성
        int res = await Fetch(id);
        cache.Add(id, res);
        return res;
    }
}




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