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