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

비밀번호

댓글 작성자
 




... 166  167  168  169  [170]  171  172  173  174  175  176  177  178  179  180  ...
NoWriterDateCnt.TitleFile(s)
807정성태11/23/200928422웹: 14. 로컬에 있는 HTML 페이지를 보호 모드에서 여는 방법
802정성태11/19/200930521.NET Framework: 167. 다른 스레드의 호출 스택 덤프 구하는 방법파일 다운로드1
801정성태11/18/200938011개발 환경 구성: 55. Hyper-V와 고성능 그래픽 카드의 성능 문제 해결 [1]
800정성태11/13/200930863VS.NET IDE: 66. 수동으로 구성해 본 VC++ 프로젝트 설정: ReleaseMinDependency
798정성태11/10/200929522개발 환경 구성: 54. .NET 개발자가 처음 설치해 본 TOMCAT [2]
797정성태11/9/200925722개발 환경 구성: 53. 물리 PC에 설치된 Windows 7을 Hyper-V로 이전하면?
796정성태11/2/200929809오류 유형: 89. Windows 7 백업 오류 - 0x80070057
795정성태11/2/200926915오류 유형: 88. TFS 2010 (beat2) 설치 오류 -TF255272
793정성태10/19/200928893.NET Framework: 166. WPF - XAML 요소의 네임스페이스와 CLR 타입 매핑
792정성태10/17/200929214웹: 13. IIS 7.5 에서 SQL Express 연결 시 오류
791정성태10/17/200933066웹: 12. 요청 페이지에 대해 빈 화면만 보이는 경우 [1]
789정성태10/13/200928965COM 개체 관련: 22. BB FlashBack SDK와 ActiveX 버전 관리 [7]
786정성태10/9/200925110개발 환경 구성: 52. 테스트를 위한 평가판 운영체제 구하기
785정성태10/8/200931562.NET Framework: 165. WPF - UI 업데이트를 바로 반영하고 싶다면? (2)파일 다운로드1
783정성태10/7/200929346.NET Framework: 164. WPF - 데이터 바인딩된 트리에서 부모 노드 찾는 방법 [1]파일 다운로드1
782정성태10/6/200931336개발 환경 구성: 51. Windows 7 - 다중 원격 접속(Remote Desktop) 허용
781정성태9/30/200928131.NET Framework: 163. WPF - TreeView 자동 스크롤 기능 해지 [2]파일 다운로드1
780정성태9/28/200932215Windows: 48. Windows 7/2008에서 ping을 위한 echo 요청 열기 [2]
779정성태9/24/200923613.NET Framework: 162. WPF - 중첩된 ScrollViewer의 크기 제어 - 두 번째 이야기파일 다운로드1
778정성태9/23/200925246오류 유형: 87. 시스템 시간 변경 후 Session이 맺어진 WCF 클라이언트의 예외 발생파일 다운로드1
776정성태9/17/200924336개발 환경 구성: 50. Reference assembly
775정성태9/13/200941033VC++: 37. XmlCodeGenerator를 C/C++ 코드 생성에 적용 [2]파일 다운로드1
773정성태9/5/200931667오류 유형 : 85. DEP 비호환 ActiveX 오류
772정성태9/2/200928080.NET Framework: 161. WPF - 윈도우 이벤트 가로채기 [1]파일 다운로드1
771정성태8/28/200922110.NET Framework: 160. WPF - 입력 포커스 외곽선 없애는 방법
770정성태8/26/200924486.NET Framework: 159. WCF - 같은 컴퓨터에서만 WCF 요청을 서비스하도록 설정
... 166  167  168  169  [170]  171  172  173  174  175  176  177  178  179  180  ...