다음을 통해 공유


모듈 이니셜라이저

메모

이 문서는 기능 사양입니다. 사양은 기능의 디자인 문서 역할을 합니다. 여기에는 기능 디자인 및 개발 중에 필요한 정보와 함께 제안된 사양 변경 내용이 포함됩니다. 이러한 문서는 제안된 사양 변경이 완료되고 현재 ECMA 사양에 통합될 때까지 게시됩니다.

기능 사양과 완료된 구현 간에 약간의 불일치가 있을 수 있습니다. 이러한 차이는 관련 언어 디자인 모임 (LDM) 기록 노트에 기록됩니다.

사양문서에서 기능 세부 스펙을 C# 언어 표준에 채택되는 과정에 대해 자세히 알아볼 수 있습니다.

챔피언 이슈: https://github.com/dotnet/csharplang/issues/2608

요약

.NET 플랫폼에는 어셈블리에 대한 초기화 코드 작성(기술적으로 모듈)을 직접 지원하는 기능 있지만 C#에서는 노출되지 않습니다. 이것은 다소 틈새 시나리오이지만, 한 번 겪게 되면 해결책이 상당히 고통스러워 보입니다. 이 문제로 어려움을 겪고 있는 많은 고객(Microsoft 내부 및 외부) 보고가 있으며, 문서화되지 않은 사례는 의심의 여지가 없습니다.

동기

  • 로드 시 최소한의 오버헤드와 사용자가 명시적으로 아무것도 호출할 필요 없이 라이브러리에서 즉시 일회성 초기화를 수행할 수 있도록 설정
  • 현재 static 생성자 접근 방식의 한 가지 특정 문제는 정적 생성자를 실행해야 하는지 여부를 결정하기 위해 런타임이 정적 생성자가 있는 형식의 사용에 대한 추가 검사를 수행해야 한다는 것입니다. 이렇게 하면 측정 가능한 오버헤드가 추가됩니다.
  • 사용자가 명시적으로 아무것도 호출할 필요 없이 원본 생성기가 일부 전역 초기화 논리를 실행하도록 설정

상세 디자인

메서드는 [ModuleInitializer] 특성으로 데코레이팅하여 모듈 이니셜라이저로 지정할 수 있습니다.

using System;
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class ModuleInitializerAttribute : Attribute { }
}

이 특성은 다음과 같이 사용할 수 있습니다.

using System.Runtime.CompilerServices;
class C
{
    [ModuleInitializer]
    internal static void M1()
    {
        // ...
    }
}

이 특성을 대상으로 하는 메서드에 몇 가지 요구 사항이 적용됩니다.

  1. 메서드는 반드시 static이어야 합니다.
  2. 메서드는 매개 변수가 없어야 합니다.
  3. 메서드는 void반환해야 합니다.
  4. 메서드는 제네릭이거나 제네릭 형식에 포함되어서는 안 됩니다.
  5. 포함하는 모듈에서 메서드에 액세스할 수 있어야 합니다.
    • 즉, 메서드의 유효한 접근성은 internal 또는 public합니다.
    • 이는 메서드가 로컬 함수가 될 수 없음을 의미합니다.

이 특성을 가진 하나 이상의 유효한 메서드가 컴파일에서 발견되면 컴파일러는 각 특성 메서드를 호출하는 모듈 이니셜라이저를 내보낸다. 호출은 예약된 순서이지만 결정적인 순서로 전송됩니다.

단점

왜 우리는 이 작업을 하지 말아야 하나요?

  • 모듈 이니셜라이저를 "삽입"하기 위한 기존 타사 도구는 이 기능을 요청한 사용자에게 충분할 수 있습니다.

디자인 회의

2020년 4월 8일