Microsoft MVP성태의 닷넷 이야기
.NET Framework: 1116. C# 10 - (15) CallerArgumentExpression 특성 추가 [링크 복사], [링크+제목 복사],
조회: 17426
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)
(시리즈 글이 15개 있습니다.)
.NET Framework: 1094. C# 10 - (1) 구조체를 생성하는 record struct
; https://www.sysnet.pe.kr/2/0/12790

.NET Framework: 1096. C# 10 - (2) 전역 네임스페이스 선언
; https://www.sysnet.pe.kr/2/0/12792

.NET Framework: 1097. C# 10 - (3) 개선된 변수 초기화 판정
; https://www.sysnet.pe.kr/2/0/12793

.NET Framework: 1099. C# 10 - (4) 상수 문자열에 포맷 식 사용 가능
; https://www.sysnet.pe.kr/2/0/12796

.NET Framework: 1100. C# 10 - (5) 속성 패턴의 개선
; https://www.sysnet.pe.kr/2/0/12799

.NET Framework: 1101. C# 10 - (6) record class 타입의 ToString 메서드를 sealed 처리 허용
; https://www.sysnet.pe.kr/2/0/12801

.NET Framework: 1103. C# 10 - (7) Source Generator V2 APIs
; https://www.sysnet.pe.kr/2/0/12804

.NET Framework: 1104. C# 10 - (8) 분해 구문에서 기존 변수의 재사용 가능
; https://www.sysnet.pe.kr/2/0/12805

.NET Framework: 1105. C# 10 - (9) 비동기 메서드가 사용할 AsyncMethodBuilder 선택 가능
; https://www.sysnet.pe.kr/2/0/12807

.NET Framework: 1108. C# 10 - (10) 개선된 #line 지시자
; https://www.sysnet.pe.kr/2/0/12812

.NET Framework: 1109. C# 10 - (11) Lambda 개선
; https://www.sysnet.pe.kr/2/0/12813

.NET Framework: 1113. C# 10 - (12) 문자열 보간 성능 개선
; https://www.sysnet.pe.kr/2/0/12826

.NET Framework: 1114. C# 10 - (13) 단일 파일 내에 적용되는 namespace 선언
; https://www.sysnet.pe.kr/2/0/12828

.NET Framework: 1115. C# 10 - (14) 구조체 타입에 기본 생성자 정의 가능
; https://www.sysnet.pe.kr/2/0/12829

.NET Framework: 1116. C# 10 - (15) CallerArgumentExpression 특성 추가
; https://www.sysnet.pe.kr/2/0/12835




C# 10 - (15) CallerArgumentExpression 특성 추가

지난 C# 5.0에 호출자 정보로 다음의 3가지 특성이 제공되었습니다.

C# 5.0에 새로 추가된 Caller Info 특성
; https://www.sysnet.pe.kr/2/0/1134

  • CallerMemberName
  • CallerFilePath
  • CallerLineNumber

그동안 이와 관련한 기능 추가가 없다가, C# 10에 들어서야 CallerArgumentExpression 특성 1개가 또 추가되는군요. ^^ 간단한 사용법을 보면 금방 어떤 것인지 이해가 되실 것입니다. ^^

using System.Runtime.CompilerServices;

public static class Program
{
    public static void Main(string [] args)
    {
        MyDebug.Assert(args.Length == 1);
        MyDebug.Assert(Environment.CurrentDirectory == "c:/temp");
    }
}

public static class MyDebug
{
    public static void Assert(bool condition, [CallerArgumentExpression("condition")] string message = null)
    {
        if (condition == false)
        {
            Console.WriteLine("Assert failed: " + message);
        }
    }
}

/* 출력 결과
Assert failed: args.Length == 1
Assert failed: Environment.CurrentDirectory == "c:/temp"
*/

보는 바와 같이 이전의 호출자 정보처럼 CallerArgumentExpression 특성이 붙은 인자는 기본값이 있어야 하고 그 특성에 전달된 "condition"은 해당 메서드에 전달된 또 다른 매개 변수의 이름이어야 합니다.

C# 10 컴파일러는, 저렇게 CallerArgumentExpression이 지정된 메서드가 호출되면, 지정된 이름의 매개 변수로 전달된 표현식을 문자열 그대로 특성이 지정된 변수에 전달합니다. 즉, 위의 소스 코드를 C# 10 컴파일러는 다음과 같이 변환해 빌드하는 것입니다.

public static class Program
{
    public static void Main(string [] args)
    {
        MyDebug.Assert(args.Length == 1, "args.Length == 1");
        MyDebug.Assert(Environment.CurrentDirectory == "c:/temp", "Environment.CurrentDirectory == \"c:/temp\"");
    }
}

실제로 이 기능의 공식 문서에는 진단/테스트 API들에서의 오류 메시지 보완을 위한 것이라고 나옵니다.

CallerArgumentExpression
; https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression

Allow developers to capture the expressions passed to a method, to enable better error messages in diagnostic/testing APIs and reduce keystrokes.

따라서 단위 테스트나 로깅 프로젝트를 사용할 때 유용하게 사용할 수 있을 것입니다.

참고로 이 기능 역시 "C# 10 - (3) 개선된 변수 초기화 판정"과 마찬가지로 Visual Studio 2022 Preview 3.1에서 빌드하면 .NET 5 + C# 9, .NET Framework + C# 10 프로젝트에서도 잘 동작합니다. 반면, Visual Studio 2019(16.11.1)에서 빌드하면 동작하지 않습니다.

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




그나저나, 위와 같은 경우에 아쉽게도 CallerArgumentExpression에 인자의 이름을 문자열로 하드 코딩해 전달해야 하는 것을 nameof로 바꾸면 좋지 않을까요?

public static void Assert(bool condition, [CallerArgumentExpression("condition")] string message = null)

public static void Assert(bool condition, [CallerArgumentExpression(nameof(condition))] string message = null)

저런 경우는 "C# 10 - (13) 문자열 보간 성능 개선"에서도 InterpolatedStringHandlerArgument를 지정할 때도 나옵니다.

public static string Create(IFormatProvider provider, 
    [InterpolatedStringHandlerArgument("provider")] ref DefaultInterpolatedStringHandler handler) =>
        handler.ToStringAndClear();

public static string Create(IFormatProvider provider, 
    [InterpolatedStringHandlerArgument(nameof(provider))] ref DefaultInterpolatedStringHandler handler) =>
        handler.ToStringAndClear();

아쉽게도 C# 10에서는 오류가 발생하지만, 현재 "C# Next"로 "nameof(parameter)"가 예정돼 있으니 조금만 기다리시면 되겠습니다. ^^




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




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 3/1/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2022-07-04 03시47분
[semir4in] 함수를 통과하면 입력 변수의 이름 대신 매개 변수의 이름만 얻게 됐었는데, CallerArgumentExpression 으로 해결할 수 있게 됐네요. 테스트 케이스 작성할 때 큰 도움이 됐습니다. 고맙습니다!
[guest]
2022-07-25 09시33분
참고로 이 기능은 C/C++의 문자열화 연산화 "#"를 사용한 매크로와 유사합니다.

Stringizing operator (#)
; https://learn.microsoft.com/en-us/cpp/preprocessor/stringizing-operator-hash

3.4 Stringizing
; https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing
정성태

... 91  92  93  94  [95]  96  97  98  99  100  101  102  103  104  105  ...
NoWriterDateCnt.TitleFile(s)
11559정성태6/25/201828615개발 환경 구성: 384. 영문 설정의 Windows 10 명령행 창(cmd.exe)의 한글 지원 [6]
11558정성태6/24/201822246.NET Framework: 775. C# 7.3 - unmanaged(blittable) 제네릭 제약파일 다운로드1
11557정성태6/22/201821698.NET Framework: 774. C# - blittable 타입이란?파일 다운로드1
11556정성태6/19/201828576.NET Framework: 773. C# 7.3 - 구조체의 고정 크기를 갖는 fixed 배열 필드에 대한 직접 접근 가능 [1]파일 다운로드1
11555정성태6/18/201820271.NET Framework: 772. C# 7.3 - 사용자 정의 타입에 fixed 적용 가능(Custom fixed)파일 다운로드1
11554정성태6/17/201822293.NET Framework: 771. C# 7.3 - 자동 구현 속성에 특성 적용 가능(Attribute on backing field)
11553정성태6/15/201821882.NET Framework: 770. C# 7.3 - 개선된 메서드 선택 규칙 3가지(Improved overload candidates)파일 다운로드1
11552정성태6/15/201823868.NET Framework: 769. C# 7.3에서 개선된 문법 4개(Support == and != for tuples, Ref Reassignment, Constraints, Stackalloc initializers)파일 다운로드1
11551정성태6/14/201820451개발 환경 구성: 383. BenchmarkDotNet 사용 시 주의 사항
11550정성태6/13/201820347.NET Framework: 768. BenchmarkDotNet으로 Span<T> 성능 측정 [2]
11549정성태6/13/201821989개발 환경 구성: 382. BenchmarkDotNet에서 생성한 BuildPlots.R 파일을 실행하는 방법
11548정성태6/13/201819236오류 유형: 470. .NET Core + BenchmarkDotNet 실행 시 프레임워크를 찾지 못하는 문제
11547정성태6/13/201824323.NET Framework: 767. BenchmarkDotNet 라이브러리 소개파일 다운로드1
11546정성태6/12/201824497.NET Framework: 766. C# 7.2의 특징 - GC 및 메모리 복사 방지를 위한 struct 타입 개선 [9]파일 다운로드1
11545정성태6/11/201822752오류 유형: 469. .NET Core 프로젝트를 Visual Studio에서 실행 시 System.BadImageFormatException 발생하는 경우 [1]
11544정성태6/10/201822336.NET Framework: 765. C# 7.2 - 숫자 리터럴의 선행 밑줄과 뒤에 오지 않는 명명된 인수
11543정성태6/9/201821900.NET Framework: 764. C# 7.2 - private protected 접근자 추가파일 다운로드1
11542정성태6/9/201860298개발 환경 구성: 381. Azure Web App 확장 예제 - Remove Custom Headers
11541정성태6/9/201819493개발 환경 구성: 380. Azure Web App 확장 배포 방법 [1]
11540정성태6/9/201820278개발 환경 구성: 379. Azure Web App 확장 예제 제작 [2]
11539정성태6/8/201820058.NET Framework: 763. .NET Core 2.1 - Tiered Compilation 도입파일 다운로드1
11538정성태6/8/201819346.NET Framework: 762. .NET Core 2.1 - 확장 도구(Tools) 관리 [1]
11537정성태6/8/201823866.NET Framework: 761. C# - SmtpClient로 SMTP + SSL/TLS 서버를 이용하는 방법 [5]
11536정성태6/7/201821481.NET Framework: 760. Microsoft Build 2018 - The future of C# 동영상 내용 정리 [1]파일 다운로드1
11535정성태6/7/201823310.NET Framework: 759. C# - System.Span<T> 성능 [1]
11534정성태6/6/201829073.NET Framework: 758. C# 7.2 - Span<T> [6]
... 91  92  93  94  [95]  96  97  98  99  100  101  102  103  104  105  ...