Microsoft MVP성태의 닷넷 이야기
.NET Framework: 1116. C# 10 - (15) CallerArgumentExpression 특성 추가 [링크 복사], [링크+제목 복사],
조회: 17336
글쓴 사람
정성태 (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
정성태

... 151  152  153  154  155  156  157  158  159  [160]  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1048정성태5/27/201132213개발 환경 구성: 123. Apache 소스를 윈도우 환경에서 빌드하기
1047정성태5/27/201126072.NET Framework: 217. Firebird ALinq Provider - 날짜 필드에 대한 낙관적 동시성 쿼리 오류
1046정성태5/26/201130710.NET Framework: 216. 라이선스까지도 뛰어넘는 .NET Profiler [5]
1045정성태5/24/201131797.NET Framework: 215. 닷넷 System.ComponentModel.LicenseManager를 이용한 라이선스 적용 [1]파일 다운로드1
1044정성태5/24/201132362오류 유형: 122. zlib 빌드 오류 - inflate.obj : error LNK2001: unresolved external symbol _inflate_fast
1043정성태5/24/201131305.NET Framework: 214. 무료 Linq Provider - DbLinq를 이용한 Firebird 접근파일 다운로드1
1042정성태5/23/201137653개발 환경 구성: 122. PHP 소스를 윈도우 환경에서 빌드하기
1041정성태5/22/201128569.NET Framework: 213. Linq To SQL - ALinq Provider를 이용하여 Firebird 사용파일 다운로드1
1040정성태5/21/201138912개발 환경 구성: 121. .NET 개발자가 처음 설치해 본 Apache + PHP [2]
1039정성태5/17/201131602.NET Framework: 212. Firebird 데이터베이스와 ADO.NET [2]파일 다운로드1
1038정성태5/16/201133570개발 환경 구성: 120. .NET 프로그래머에게도 유용한 Firebird 무료 데이터베이스 [2]
1037정성태5/11/201128401개발 환경 구성: 119. Visual Studio Professional 이하 버전에서도 TFS의 정적 코드 분석 정책 연동이 가능할까? [3]
1036정성태5/7/201194235오류 유형: 121. Access DB에 대한 32bit/64bit OLE DB Provider 관련 오류 [11]
1035정성태5/7/201128947오류 유형: 120. File cannot be opened. Ensure it is a valid Data Link file.
1034정성태5/2/201126023.NET Framework: 211. 파일 잠금 없이 .NET 어셈블리의 버전을 구하는 방법 [2]파일 다운로드1
1033정성태5/1/201131722웹: 19. IIS Express - appcmd.exe를 이용한 applicationHost.config 변경 [2]
1032정성태5/1/201128367웹: 18. IIS Express를 NT 서비스로 변경
1031정성태4/30/201129518웹: 17. IIS Express - "IIS Installed Versions Manager Interface"의 IIISExpressProcessUtility 구하는 방법 [1]파일 다운로드1
1030정성태4/30/201151796개발 환경 구성: 118. IIS Express - localhost 이외의 호스트 이름으로 접근하는 방법 [4]파일 다운로드1
1029정성태4/28/201140902개발 환경 구성: 117. XCopy에서 파일/디렉터리 확인 질문 없애기 [2]
1028정성태4/27/201138301오류 유형: 119. Visual Studio 2010 SP1 설치 후 Windows Phone 개발자 도구로 인한 재설치 문제 [3]
1027정성태4/25/201127474디버깅 기술: 40. 상황별 GetFunctionPointer 반환값 정리 - x86파일 다운로드1
1026정성태4/25/201145761디버깅 기술: 39. DebugDiag 1.1을 사용한 덤프 분석 [7]
1025정성태4/24/201127820개발 환경 구성: 116. IIS 7 관리자 - Active Directory Certification Authority로부터 SSL 사이트 인증서 받는 방법 [2]
1024정성태4/22/201129186오류 유형: 118. Windows 2008 서버에서 Event Viewer / PowerShell 실행 시 비정상 종료되는 문제 [1]
1023정성태4/20/201130060.NET Framework: 210. Windbg 환경에서 확인해 본 .NET 메서드 JIT 컴파일 전과 후 [1]
... 151  152  153  154  155  156  157  158  159  [160]  161  162  163  164  165  ...