Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 15개 있습니다.)

C# 9.0 - (5) 로컬 함수에 특성 지정 가능(Attributes on local functions)

C# 9.0 - (1) 대상으로 형식화된 new 식(Target-typed new expressions)
; https://www.sysnet.pe.kr/2/0/12363

C# 9.0 - (2) localsinit 플래그 내보내기 무시(Suppress emitting localsinit flag)
; https://www.sysnet.pe.kr/2/0/12364

C# 9.0 - (3) 람다 메서드의 매개 변수 무시(Lambda discard parameters)
; https://www.sysnet.pe.kr/2/0/12365

C# 9.0 - (4) 원시 크기 정수(Native ints)
; https://www.sysnet.pe.kr/2/0/12366

C# 9.0 - (5) 로컬 함수에 특성 지정 가능(Attributes on local functions)
; https://www.sysnet.pe.kr/2/0/12372

C# 9.0 - (6) 함수 포인터(Function pointers)
; https://www.sysnet.pe.kr/2/0/12374

C# 9.0 - (7) 패턴 일치 개선 사항(Pattern matching enhancements)
; https://www.sysnet.pe.kr/2/0/12383

C# 9.0 - (8) 정적 익명 함수 (static anonymous functions)
; https://www.sysnet.pe.kr/2/0/12389

C# 9.0 - (9) 레코드 (Records)
; https://www.sysnet.pe.kr/2/0/12392

C# 9.0 - (10) 대상으로 형식화된 조건식(Target-typed conditional expressions)
; https://www.sysnet.pe.kr/2/0/12399

C# 9.0 - (11) 공변 반환 형식(Covariant return types)
; https://www.sysnet.pe.kr/2/0/12402

C# 9.0 - (12) foreach 루프에 대한 GetEnumerator 확장 메서드 지원(Extension GetEnumerator)
; https://www.sysnet.pe.kr/2/0/12403

C# 9.0 - (13) 모듈 이니셜라이저(Module initializers)
; https://www.sysnet.pe.kr/2/0/12404

C# 9.0 - (14) 부분 메서드에 대한 새로운 기능(New features for partial methods)
; https://www.sysnet.pe.kr/2/0/12405

C# 9.0 - (15) 최상위 문(Top-level statements)
; https://www.sysnet.pe.kr/2/0/12406

C# 9.0 - (16) 제약 조건이 없는 형식 매개변수 주석(Unconstrained type parameter annotations)
; https://www.sysnet.pe.kr/2/0/12423




로컬 함수는 C# 7.0부터 도입이 되었는데, 익명 함수보다 성능상 이점이 있으므로 비주얼 스튜디오의 경우 정적 분석에서 익명 함수를 사용하고 있다면 로컬 함수로 바꾸도록 권장하는 메시지가 나옵니다.

Message IDE0039 Use local function

그런데, 로컬 함수의 외형이 일반 메서드 정의와 너무나 닮아있으므로 당연히 특성(Attribute)도 적용되어야 할 듯싶지만 C# 8.0까지는 그런 경우 컴파일 오류가 발생했습니다. 다행히 C# 9.0부터는 이를 허용하므로 다음과 같이 특성을 적용하는 것이 가능합니다.

using System;
using System.Runtime.CompilerServices;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Log("Main");

        [SkipLocalsInit]
        void Log([DummyParam] string text)
        {
            int tid = Thread.CurrentThread.ManagedThreadId;
            string logText = $"[{tid}] {text}";

            Console.WriteLine(logText);
        }
    }
}

[AttributeUsage(AttributeTargets.Parameter)]
public sealed class DummyParamAttribute : Attribute
{
}

#if !NET5_0
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
    public sealed class SkipLocalsInitAttribute : Attribute
    {
    }
}
#endif

그 외에, 조건부 컴파일 특성을 지정하는 경우에는 (C# 8.0부터 로컬 함수에 적용 가능한) static 유형으로 만들어야 합니다.

static void Main(string[] args)
{
    DebugLog("Main");

    [Conditional("DEBUG")]
    static void DebugLog(string text)
    {
        // static 로컬 함수이므로 다음과 같이 args 변수를 접근하면,
        // "A static local function cannot contain a reference to 'args'" 오류 발생
        Console.WriteLine($"[{args.Length}] DEBUG: " + text);
    }
}

그리고 이 모든 것이 합쳐져서(static + attribute) extern 유형의 P/Invoke 정의도 로컬 함수로 지정할 수 있게 되었습니다.

static void Main(string[] args)
{
    MessageBox(IntPtr.Zero, "message", "title", 0);

    // extern P/Invoke 정의를 로컬 함수로도 가능
    [DllImport("User32.dll", CharSet = CharSet.Unicode)]
    static extern int MessageBox(IntPtr h, string m, string c, int type);
}

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




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 11/22/2020]

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

비밀번호

댓글 작성자
 




... 91  92  93  94  95  96  97  98  [99]  100  101  102  103  104  105  ...
NoWriterDateCnt.TitleFile(s)
11490정성태4/12/201818105.NET Framework: 739. .NET Framework 4.7.1의 새 기능 - Configuration builders [1]파일 다운로드1
11489정성태4/12/201815851오류 유형: 463. 윈도우 백업 오류 - a Volume Shadow Copy Service operation failed.
11488정성태4/12/201819563오류 유형: 462. Unhandled Exception in Managed Code Snap-in - FX:{811FD892-5EB4-4E73-A147-F1E079E36C4E}
11487정성태4/12/201817814디버깅 기술: 115. windbg - 닷넷 메모리 덤프에서 정적(static) 필드 값을 조사하는 방법
11486정성태4/11/201816948오류 유형: 461. Error MSB4064 The "ComputeOutputOnly" parameter is not supported by the "VsTsc" task
11485정성태4/11/201824859.NET Framework: 738. C# - Console 프로그램이 Ctrl+C 종료 시점을 감지하는 방법파일 다운로드1
11484정성태4/11/201826129.NET Framework: 737. C# - async를 Task 타입이 아닌 사용자 정의 타입에 적용하는 방법파일 다운로드1
11483정성태4/10/201829419개발 환경 구성: 358. "Let's Encrypt"에서 제공하는 무료 SSL 인증서를 IIS에 적용하는 방법 (2) [1]
11482정성태4/10/201821348VC++: 126. CUDA Core 수를 알아내는 방법
11481정성태4/10/201833603개발 환경 구성: 357. CUDA의 인덱싱 관련 용어 - blockIdx, threadIdx, blockDim, gridDim
11480정성태4/9/201823564.NET Framework: 736. C# - API를 사용해 Azure에 접근하는 방법 [2]파일 다운로드1
11479정성태4/9/201818455.NET Framework: 735. Azure - PowerShell로 Access control(IAM)에 새로운 계정 만드는 방법
11478정성태11/8/201921495디버깅 기술: 115. windbg - 덤프 파일로부터 PID와 환경변수 등의 정보를 구하는 방법 [1]
11477정성태4/8/201818586오류 유형: 460. windbg - sos 명령어 수행 시 c0000006 오류 발생
11476정성태4/8/201819986디버깅 기술: 114. windbg - !threads 출력 결과로부터 닷넷 관리 스레드(System.Threading.Thread) 객체를 구하는 방법
11475정성태3/28/201822634디버깅 기술: 113. windbg - Thread.Suspend 호출 시 응용 프로그램 hang 현상에 대한 덤프 분석
11474정성태3/27/201820850오류 유형: 459. xperf: error: TEST.Event: Invalid flags. (0x3ec).
11473정성태3/22/201825824.NET Framework: 734. C# - Thread.Suspend 호출 시 응용 프로그램 hang 현상파일 다운로드2
11472정성태3/22/201819425개발 환경 구성: 356. GTX 1070, GTX 960, GT 640M의 cudaGetDeviceProperties 출력 결과
11471정성태3/20/201822646VC++: 125. CUDA로 작성한 RGB2RGBA 성능 [1]파일 다운로드1
11470정성태3/20/201825379오류 유형: 458. Visual Studio - CUDA 프로젝트 빌드 시 오류 C1189, expression must have a constant value
11469정성태3/19/201818324오류 유형: 457. error MSB3103: Invalid Resx file. Could not load file or assembly 'System.Windows.Forms, ...' or one of its dependencies.
11468정성태3/19/201817593오류 유형: 456. 닷넷 응용 프로그램 실행 시 0x80131401 예외 발생
11467정성태3/19/201817434오류 유형: 455. Visual Studio Installer - 업데이트 실패
11466정성태3/18/201817961개발 환경 구성: 355. 한 대의 PC에서 2개 이상의 DirectX 게임을 실행하는 방법
11463정성태3/15/201820230.NET Framework: 733. 스레드 간의 read/write 시에도 lock이 필요 없는 경우파일 다운로드1
... 91  92  93  94  95  96  97  98  [99]  100  101  102  103  104  105  ...