Microsoft 인터페이스 정의 언어 3.0 소개

MIDL(Microsoft Interface Definition Language) 3.0은 IDL(Interface Definition Language) 파일(.idl파일) 내에서 Windows 런타임 형식을 정의하기 위한 간소화된 최신 구문입니다. 이 새로운 구문은 C, C++, C#및/또는 Java를 경험하는 모든 사용자에게 친숙할 것입니다. MIDL 3.0은 특히 C++/WinRT 런타임 클래스를 정의하는 편리한 방법으로, 이전 버전의 IDL보다 훨씬 간결합니다(디자인 길이를 3분의 2로 줄이고 적절한 기본값을 사용하여 특성으로 데코레이팅할 필요성을 줄임).

MIDL 3.0의 모양은 다음과 같습니다. 이 예제에서는 사용할 수 있는 대부분의 언어 구문 요소를 보여 줍니다.

// Photo.idl
namespace PhotoEditor
{
    delegate void RecognitionHandler(Boolean arg); // delegate type, for an event.

    runtimeclass Photo : Windows.UI.Xaml.Data.INotifyPropertyChanged // interface.
    {
        Photo(); // constructors.
        Photo(Windows.Storage.StorageFile imageFile);

        String ImageName{ get; }; // read-only property.
        Single SepiaIntensity; // read-write property.

        Windows.Foundation.IAsyncAction StartRecognitionAsync(); // (asynchronous) method.

        event RecognitionHandler ImageRecognized; // event.
    }
}

MIDL 3.0의 구문은 형식 을 정의 하기 위해 특별히 설계되었습니다. 다른 프로그래밍 언어를 사용하여 이러한 형식을 구현 합니다. MIDL 3.0을 사용하려면 Windows SDK 버전 10.0.17134.0(Windows 10, 버전 1803)(midl.exe버전 8.01.0622 이상, 스위치와 함께 /winrt 사용됨)이 필요합니다.

참고

또한 Windows 런타임 통합 참조(Windows 런타임 형식 시스템Windows 메타데이터 파일)를 참조하세요.

MIDL 1.0, 2.0 및 3.0

IDL(인터페이스 정의 언어)은 DCE/RPC(분산 컴퓨팅 환경/원격 프로시저 호출) 시스템에서 시작되었습니다. 원래 MIDL 1.0 은 COM 인터페이스 및 코클래스를 정의하기 위한 향상된 기능을 갖춘 DCE/RPC IDL입니다.

업데이트된 MIDL 2.0 구문(MIDLRT라고도 함)은 Windows 플랫폼에 대한 Windows 런타임 API를 선언하기 위해 Microsoft 내에서 개발되었습니다. Windows SDK 폴더 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\winrt 를 보면 MIDL 2.0 구문으로 작성된 파일의 .idl 예제가 표시됩니다. ABI(애플리케이션 이진 인터페이스) 형식으로 선언된 기본 제공 Windows 런타임 API입니다. 이러한 파일은 주로 도구를 사용하기 위해 존재합니다. 매우 낮은 수준의 코드를 작성하지 않는 한 이 양식에서 이러한 API를 작성하거나 사용하지 않습니다.

클래식 MIDLRT에서 MIDL 3.0으로의 전환도 참조하세요.

MIDL 3.0은 훨씬 더 간단하고 최신 구문으로, Windows 런타임 API를 선언하는 것이 목적입니다. 또한 프로젝트에서 사용할 수 있습니다. 특히 C++/WinRT 런타임 클래스를 정의할 수 있습니다. 기본 제공 Windows 런타임 API의 경우 C++/WinRT에서 사용할 헤더는 폴더 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt내 SDK의 일부입니다.

MIDL 3.0에 대한 사용 사례

일반적으로 모든 Windows 런타임 API는 모든 Windows 런타임 언어 프로젝션에서 사용할 수 있도록 설계되었습니다. 이는 부분적으로 Windows 런타임 형식을 Windows 런타임 API와 단독으로 전달하도록 선택하여 수행됩니다. Windows 런타임 API와 원시 COM 인터페이스를 전달하는 것은 유효한 디자인 결정이지만, 이렇게 하면 특정 Windows 런타임 API의 소비자가 C++ 애플리케이션으로 제한됩니다. 이 기술은 상호 운용 시나리오(예: Direct3D와 XAML 간에 상호 운용하는 경우)에서 확인할 수 있습니다. Direct3D가 그림에 있으므로 시나리오는 반드시 C++ 애플리케이션으로 좁혀집니다. 따라서 COM 인터페이스가 필요한 API는 내재된 것 이상으로 추가적인 제한을 적용하지 않습니다. 예를 들어 C++ 애플리케이션은 IDXGISwapChain 인터페이스 포인터를 가져온 다음 ISwapChainPanelNative::SetSwapChain 메서드에 전달할 수 있습니다. 예를 들어 C# 애플리케이션은 IDXGISwapChain 을 가져올 수 없으므로 이러한 이유로 해당 메서드를 사용할 수 없습니다. 이러한 interop 관련 예외는 interop 헤더에 있습니다(예: windows.ui.xaml.media.dxinterop.h.).

C++를 넘어 Windows 런타임 언어 프로젝션에 노출하려는 COM 구성 요소의 기능 또는 기능이 있는 경우 COM 구성 요소(예: DirectX)를 직접 만들고 사용하는 C++ WINDOWS 런타임 구성 요소(예: DirectX)를 만들고 해당 기능의 일부 하위 집합을 a 형식으로 노출하는 C++ Windows 런타임 구성 요소를 만들 수 있습니다. Windows 런타임 형식만 사용하고 반환하는 Windows 런타임 API 표면입니다. 그런 다음 Windows 런타임 언어 프로젝션으로 작성된 애플리케이션에서 해당 WRC를 사용할 수 있습니다.

정의 구조 및 명령줄에서 midl.exe 호출

MIDL 3.0 정의의 주요 조직 개념은 네임스페이스, 형식 및 멤버입니다. MIDL 3.0 원본 파일( .idl 파일)에는 형식 및/또는 하위 네임스페이스인 하나 이상의 네임스페이스가 포함되어 있습니다. 각 형식에는 0개 이상의 멤버가 포함됩니다.

  • 클래스, 인터페이스, 구조체 및 열거형은 형식입니다.
  • 메서드, 속성, 이벤트 및 필드는 멤버의 예입니다.

MIDL 3.0 원본 파일을 컴파일하면 컴파일러(midl.exe)는 Windows 런타임 메타데이터 파일(일반적으로 파일)을 .winmd 내보냅니다.

// Bookstore.idl
namespace Bookstore
{
    runtimeclass BookSku : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        BookSku();
        BookSku(Single price, String authorName, String coverImagePath, String title);

        Single Price;

        String AuthorName{ get; };
        Windows.UI.Xaml.Media.ImageSource CoverImage{ get; };
        String CoverImagePath{ get; };
        String Title{ get; };

        Boolean Equals(BookSku other);
        void ApplyDiscount(Single percentOff);
    }
}

Windows 런타임 형식의 네임스페이스는 형식 이름의 일부가 되므로 위의 예제에서는 Bookstore.BookSku라는 런타임 클래스를 정의합니다. 네임스페이스를 표현하지 않고 는 BookSku 를 표현하는 언어 독립적 방법이 없습니다.

이 클래스는 Windows.UI.Xaml.Data.INotifyPropertyChanged 인터페이스를 구현합니다. 클래스에는 두 개의 생성자, 읽기-쓰기 속성(Price), 일부 읽기 전용 속성(Title을 통한 AuthorName) 및 EqualsApplyDiscount라는 두 개의 메서드가 포함됩니다. float가 아닌 Single 형식을 사용합니다. 그리고 해당 문자열 에는 대문자 "S"가 있습니다.

Visual Studio는 C++/WinRT VSIX(Visual Studio Extension)를 통해 MIDL 3.0을 컴파일하는 데 가장 적합한 환경을 제공합니다. C++/WinRT 및 VSIX에 대한 Visual Studio 지원을 참조하세요.

그러나 명령줄에서 MIDL 3.0을 컴파일할 수도 있습니다. 이 예제의 소스 코드가 이름이 지정된 Bookstore.idl파일에 저장되면 아래 명령을 실행할 수 있습니다. 필요한 경우 명령에 사용되는 SDK 버전 번호(10.0.17134.0)를 업데이트할 수 있습니다.

midl /winrt /metadata_dir "%WindowsSdkDir%References\10.0.17134.0\windows.foundation.foundationcontract\3.0.0.0" /h "nul" /nomidl /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd" /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.UniversalApiContract\6.0.0.0\Windows.Foundation.UniversalApiContract.winmd" /reference "%WindowsSdkDir%\References\10.0.17134.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd" Bookstore.idl

이 도구는 midl.exe 예제를 컴파일하고 명명된 Bookstore.winmd 메타데이터 파일을 생성합니다(기본적으로 파일 이름이 .idl 사용됨).

둘 이상의 IDL 파일을 사용하는 경우(이에 대한 자세한 내용은 런타임 클래스를 Midl 파일(.idl)로 팩터링 참조) 결과 .winmd 파일을 모두 루트 네임스페이스와 동일한 이름의 단일 파일로 병합합니다. 최종 .winmd 파일은 API 소비자가 참조하는 파일입니다.

이 경우 BookSkuBookstore 네임스페이스에서 유일한 런타임 클래스이므로 단계를 저장하고 네임스페이 .idl 스의 파일 이름을 지정했습니다.

또한 이 명령을 사용하여 where 설치된 위치를 midl.exe 확인할 수 있습니다.

where midl

다른 .idl 파일의 한 .idl 파일에 정의된 형식을 사용하려면 지시문을 사용합니다import. 자세한 내용 및 코드 예제는 XAML 컨트롤을 참조하세요. C++/WinRT 속성에 바인딩합니다. 물론 기본 제공 또는 타사 구성 요소를 사용하는 경우 파일에 액세스할 수 .idl 없습니다. 예를 들어 직접 모드 2D 그래픽 렌더링을 위해 Win2D Windows 런타임 API를 사용할 수 있습니다. 위의 명령은 스위치를 /reference 사용하여 Windows 런타임 메타데이터(.winmd) 파일을 참조했습니다. 다음 예제에서는 해당 스위치를 다시 사용하여 있는 시나리오 Bookstore.winmd를 상상하지만 그렇지는 않습니다 Bookstore.idl.

// MVVMApp.idl
namespace MVVMApp
{
    runtimeclass ViewModel
    {
        ViewModel();
        Bookstore.BookSku BookSku{ get; };
    }
}

위의 예제에 대한 소스 코드가 명명 MVVMApp.idl된 파일에 저장된 경우 아래 명령을 실행하여 참조 Bookstore.winmd할 수 있습니다.

midl /winrt /metadata_dir "%WindowsSdkDir%References\10.0.17134.0\windows.foundation.foundationcontract\3.0.0.0" /h "nul" /nomidl /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd" /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.UniversalApiContract\6.0.0.0\Windows.Foundation.UniversalApiContract.winmd" /reference "%WindowsSdkDir%\References\10.0.17134.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd" /reference Bookstore.winmd MVVMApp.idl

네임스페이스

네임스페이스가 필요합니다. 네임스페이스 블록의 범위에 정의된 모든 형식의 이름 앞에 네임스페이스 이름을 접두사로 지정합니다. 네임스페이스에는 하위 네임스페이스 선언도 포함될 수 있습니다. 하위 네임스페이스 범위에 정의된 형식의 이름에는 포함된 모든 네임스페이스 이름의 접두사가 있습니다.

아래 예제는 동일한 Windows.Foundation.Uri 클래스를 선언하는 두 가지 방법입니다(보듯이 마침표는 중첩된 네임스페이스의 수준을 구분합니다).

namespace Windows.Foundation
{
    runtimeclass Uri : IStringable
    {
        ...
    }
}
namespace Windows
{
    namespace Foundation
    {
        runtimeclass Uri : IStringable
        {
            ...
        }
    }
}

다음은 네임스페이스 및 해당 형식을 중첩된 방식으로 선언하는 것이 합법적임을 보여주는 또 다른 예입니다.

namespace RootNs.SubNs1
{
    runtimeclass MySubNs1Class
    {
        void DoWork();
    }

    namespace SubNs2
    {
        runtimeclass MySubNs2Class
        {
            void DoWork();
        }
    }
}

그러나 이전 네임스페이스를 닫고 이와 같이 새 네임스페이스를 여는 것이 더 일반적입니다.

namespace RootNs.SubNs1
{
    runtimeclass MySubNs1Class
    {
        void DoWork();
    }
}

namespace RootNs.SubNs1.SubNs2
{
    runtimeclass MySubNs2Class
    {
        void DoWork();
    }
}

형식

MIDL 3.0에는 값 형식과 참조 형식이라는 두 가지 종류의 데이터 형식이 있습니다. 값 형식의 변수에는 해당 데이터가 직접 포함됩니다. 참조 형식의 변수는 해당 데이터에 대한 참조를 저장합니다(이러한 변수를 개체라고도 함).

두 개의 참조 형식 변수가 동일한 개체를 참조할 수 있습니다. 따라서 한 변수에 대한 작업은 다른 변수에서 참조하는 개체에 영향을 줍니다. 값 형식을 사용하면 변수 각각에 고유한 데이터 복사본이 있으며 한 변수에 대한 작업이 다른 변수에 영향을 줄 수 없습니다.

MIDL 3.0의 값 형식은 단순 형식, 열거형 형식, 구조체 형식 및 nullable 형식으로 더 나뉩니다.

MIDL 3.0의 참조 형식은 클래스 형식, 인터페이스 형식 및 대리자 형식으로 더 나뉩니다.

MIDL 3.0의 형식 시스템에 대한 개요는 다음과 같습니다. 이전 버전의 MIDL과 달리 이러한 형식에는 별칭을 사용할 수 없습니다.

범주 설명
값 형식 단순 형식 부호 있는 정수: Int16, Int32, Int64
부호 없는 정수: UInt8, UInt16, UInt32, UInt64
유니코드 문자: Char (UTF-16LE, 16비트 유니코드 코드 단위를 나타낸다)
유니코드 문자열: 문자열
IEEE 부동 소수점: Single, Double
부울: 부울
128비트 UUID: Guid
열거형 E {...} 양식 열거형의 사용자 정의 형식
구조체 형식 양식 구조체 S {...}의 사용자 정의 형식
Nullable 유형 null 값이 있는 다른 모든 값 형식의 확장
참조 형식 클래스 형식 다른 모든 형식의 Ultimate 기본 클래스: 개체
양식 런타임 클래스 C {...}의 사용자 정의 형식
인터페이스 형식 사용자 정의 형식의 양식 인터페이스 I {...}
대리자 형식 양식 대리자 <returnType> D(...)의 사용자 정의 형식

7개의 정수 계열 형식은 8비트 부호 없는 데이터를 지원합니다. 부호 있거나 서명되지 않은 형식의 16비트, 32비트 및 64비트 값

두 부동 소수점 형식 인 SingleDouble은 각각 32비트 단정밀도 및 64비트 배정밀도 IEEE 754 형식을 사용하여 데이터를 나타냅니다.

MIDL 3.0의 부울 형식은 부울 값을 나타냅니다. false또는 true .

MIDL 3.0의 문자 및 문자열에는 유니코드 문자가 포함됩니다. Char 형식은 UTF-16LE 코드 단위를 나타냅니다. 문자열 형식은 UTF-16LE 코드 단위의 시퀀스를 나타냅니다.

다음 표에서는 MIDL 3.0의 숫자 형식을 요약합니다.

범주 비트 유형 범위/정밀도
부 서명된 정수 계열 16 Int16 –32,768...32,767
32 Int32 –2,147,483,648...2,147,483,647
64 Int64 –9,223,372,036,854,775,808...9,223,372,036,854,775,807
부호 없는 정수 8 UInt8 0...255
16 UInt16 0...65,535
32 UInt32 0...4,294,967,295
64 UInt64 0...18,446,744,073,709,551,615
부동 소수점 32 Single 1.5 × 10-45 에서 3.4 × 1038, 7자리 정밀도
64 double 5.0 × 10-324 에서 1.7 × 10308, 15자리 정밀도

MIDL 3.0 원본 파일은 형식 정의를 사용하여 새 형식을 만듭니다. 형식 정의는 새 형식의 이름과 멤버를 지정합니다. 이러한 MIDL 3.0 형식 범주는 사용자가 정의할 수 있습니다.

  • 특성 유형,
  • 구조체 형식,
  • 인터페이스 형식,
  • runtimeclass 형식,
  • 대리자 형식 및
  • 열거형 형식입니다.

특성 형식은 다른 형식 정의에 적용할 수 있는 Windows 런타임 특성을 정의합니다. 특성은 특성이 적용되는 형식에 대한 메타데이터를 제공합니다.

구조체 형식은 데이터 멤버(필드)를 포함하는 Windows 런타임 구조를 정의합니다. 구조체는 값 형식이며 힙 할당이 필요하지 않습니다. 구조체 형식의 데이터 멤버는 값 형식 또는 nullable 형식이어야 합니다. 구조체 형식은 상속을 지원하지 않습니다.

인터페이스 형식은 명명된 함수 멤버 집합인 Windows 런타임 인터페이스를 정의합니다. 인터페이스는 인터페이스 구현이 하나 이상의 지정된 추가(필수) 인터페이스를 구현해야 한다고 지정할 수 있습니다. 모든 인터페이스 형식은 Windows 런타임 IInspectable 인터페이스에서 직접 파생됩니다.

런타임 클래스 형식은 Windows 런타임 클래스(런타임 클래스)를 정의합니다. 런타임 클래스에는 속성, 메서드 및 이벤트일 수 있는 멤버가 포함됩니다.

대리자 형식은 특정 매개 변수 목록 및 반환 형식이 있는 메서드에 대한 참조를 나타내는 Windows 런타임 대리자를 정의합니다. 대리자를 사용하면 메서드를 매개 변수로 전달할 수 있는 엔터티로 처리할 수 있습니다. 대리자는 다른 언어에서 찾을 수 있는 함수 포인터의 개념과 비슷합니다. 함수 포인터와 달리 대리자는 개체 지향적이며 형식이 안전합니다.

열거형 형식은 명명된 상수가 있는 고유 형식입니다. 모든 열거형 형식에는 암시적 기본 형식이 있습니다. Int32 또는 UInt32 중 하나. 열거형 형식의 값 집합은 기본 형식의 값 집합과 동일합니다.

MIDL 3.0은 세 가지 추가 형식 범주를 지원합니다.

  • 1차원 배열 형식,
  • nullable 값 형식 및
  • 개체 형식입니다.

1차원 배열을 사용하려면 1차원 배열을 선언할 필요가 없습니다. 대신, 배열 형식은 형식 이름을 대괄호로 묶어 생성합니다. 예를 들어 Int32[]Int32의 1차원 배열입니다.

마찬가지로 nullable 값 형식도 사용할 수 있기 전에 정의할 필요가 없습니다. Nullable이 아닌 각 값 형식 T(문자열 제외)에 대해 추가 값을 null보유할 수 있는 해당 nullable 형식 Windows.Foundation.IReference<T>가 있습니다. 예를 들어 Windows.Foundation.IReference<Int32> 는 32비트 정수 또는 값을 null보유할 수 있는 형식입니다. 또한 IReference<T를 참조하세요>.

마지막으로 MIDL 3.0은 Windows 런타임 IInspectable 인터페이스에 매핑되는 개체 형식을 지원합니다. 인터페이스런타임 클래스 참조 형식은 개념적으로 개체 형식에서 파생됩니다. 대리자는 그렇지 않습니다.

열거된 값의 식

MIDL 3.0에서는 열거형 형식의 명명된 상수 값 정의에만 식을 사용할 수 있습니다. 즉, 열거형 이니셜라이저에 있습니다.

식은 피연산자와연산자에서 생성됩니다. 식의 연산자는 피연산자에서 적용할 연산을 나타냅니다. 연산자의 예로는 +, -, *, /및 new. 피연산자의 예로는 리터럴, 필드, 지역 변수 및 식이 있습니다.

식에 여러 연산자가 포함된 경우 연산자의 ‘우선 순위’는 개별 연산자가 평가되는 순서를 제어합니다. 예를 들어 * 연산자의 우선 순위가 + 연산자보다 높기 때문에 식 x + y * z는 x + (y * z)로 평가됩니다. 논리 연산은 비트 연산보다 우선 순위가 낮습니다.

다음 표에서는 MIDL 3.0 연산자를 요약하여 우선 순위가 가장 높은 연산자에서 가장 낮은 순서로 연산자 범주를 나열합니다. 동일한 범주의 연산자는 우선 순위가 같습니다.

범주 설명
x++ 후위 증가
x-- 후위 감소
단항 연산자 +x ID
-X 부정
!x 논리 부정
~x 비트 부정 연산
++x 전위 증가
--x 전위 감소
곱셈 x * y 곱하기
x / y 사업부
x % y 나머지
더하기 x + y 더하기, 문자열 연결, 대리자 조합
x – y 빼기, 대리자 제거
Shift 키 x << y 왼쪽 시프트
x >> y 오른쪽 시프트
비트 AND x & y 정수 비트 AND
비트 XOR x ^ y 정수 비트 XOR
비트 OR x | y 정수 비트 OR
논리적 AND x && y 부울 논리 AND
논리적 OR x || y 부울 논리 OR

클래스

클래스 (또는 런타임 클래스)는 MIDL 3.0 형식의 가장 기본적인 형식입니다. 클래스는 단일 단위의 메서드, 속성 및 이벤트 집계에 대한 정의입니다. 클래스는 상속다형성( 파생 클래스 가 기본 클래스를 확장하고 특수화할 수 있는 메커니즘) 을 지원합니다.

클래스 정의를 사용하여 새 클래스 형식을 정의합니다. 클래스 정의는 키워드, 클래스 이름, 기본 클래스(지정된 경우) 및 클래스에서 구현하는 인터페이스를 지정 runtimeclass 하는 헤더로 시작합니다. 머리글 뒤에 클래스 본문이 있으며, 이 본문은 구분 기호 {와 }사이에 작성된 멤버 선언 목록으로 구성됩니다.

다음은 Area라는 간단한 클래스의 정의입니다.

runtimeclass Area
{
    Area(Int32 width, Int32 height);

    Int32 Height;
    Int32 Width;

    static Int32 NumberOfAreas { get; };
}

이는 개의 Int32 매개 변수, Height 및Width라는 두 개의 Int32 읽기-쓰기 속성 및 NumberOfAreas라는 정적 읽기 전용 속성을 사용하는 생성자가 있는 Area라는 새 Windows 런타임 클래스를 정의합니다.

기본적으로 런타임 클래스는 봉인되고 파생은 허용되지 않습니다. 기본 클래스를 참조하세요.

XAML을 뷰 모델에 바인딩하려면 뷰 모델 런타임 클래스를 MIDL에서 정의해야 합니다. 자세한 내용은 XAML 컨트롤, C++/WinRT 속성에 바인딩을 참조하세요.

클래스가 인스턴스를 지원하지 않으며 따라서 런타임 클래스 정의 static 에 키워드를 접두사로 지정하여 정적 멤버만 포함해야 한다고 선언할 수 있습니다. 비정적 멤버를 클래스에 추가하면 컴파일 오류가 발생합니다.

static runtimeclass Area
{
    static Int32 NumberOfAreas { get; };
}

정적 클래스는 빈 클래스와 다릅니다. 빈 클래스도 참조하세요.

런타임 클래스 정의에 키워드를 접두사로 지정하여 클래스 정의 partial 가 불완전함을 나타낼 수 있습니다. 컴파일러에서 발생하는 모든 부분 클래스 정의는 단일 런타임 클래스로 결합됩니다. 이 기능은 주로 일부 부분 클래스가 기계 생성되는 XAML 제작 시나리오를 위한 것입니다.

한정자 의미
static 클래스에 인스턴스가 없습니다. 따라서 정적 멤버만 허용됩니다.
부분 클래스 정의가 불완전합니다.

고급 한정자에 대한 컴퍼지션 및 활성화 를 참조하세요.

멤버 액세스 한정자

MIDL 3.0은 Windows 런타임 형식의 공용 표면을 설명하는 정의 언어이므로 멤버의 공용 접근성을 선언하는 명시적 구문이 필요하지 않습니다. 모든 멤버는 암시적으로 공용입니다. MIDL 3.0이 (효과적으로 중복) public 키워드를 요구하거나 허용하지 않는 이유입니다.

기본 클래스

클래스 정의는 콜론과 기본 클래스의 이름을 사용하여 클래스 이름 및 형식 매개 변수에 따라 기본 클래스를 지정할 수 있습니다. 기본 클래스 사양을 생략하는 것은 개체 형식에서 파생되는 것과 같습니다(즉, IInspectable에서).

참고

뷰 모델 클래스(실제로 애플리케이션에서 정의하는 모든 런타임 클래스)는 기본 클래스에서 파생되지 않아도 됩니다.

기본 클래스에서 파생 되는 애플리케이션에서 정의하는 모든 런타임 클래스를 작성 가능한 클래스라고 합니다. 또한 구성 가능 클래스에 관련된 제약 조건이 있습니다. 애플리케이션이 Visual Studio 및 Microsoft Store에서 제출의 유효성 검사에 사용되는 Windows 앱 인증 키트 테스트를 통과하여 Microsoft Store로 성공적으로 수집되려면 구성 가능 클래스는 기본적으로 Windows 기본 클래스에서 파생되어야 합니다. 즉, 상속 계층 구조의 루트에 있는 클래스는 Windows.* 네임스페이스에서 시작되는 형식이어야 합니다.

자세한 내용은 XAML 컨트롤, C++/WinRT 속성에 바인딩을 참조하세요.

다음 예제에서 볼륨 의 기본 클래스는 Area이고 Area 의 기본 클래스는 Windows.UI.Xaml.DependencyObject입니다.

unsealed runtimeclass Area : Windows.UI.Xaml.DependencyObject
{
    Area(Int32 width, Int32 height);
    Int32 Height;
    Int32 Width;
}

runtimeclass Volume : Area
{
    Volume(Int32 width, Int32 height, Int32 depth);
    Int32 Depth;
}

참고

여기서 영역볼륨 은 동일한 원본 파일에 정의됩니다. 장단점을 알아보려면 런타임 클래스를 Midl 파일(.idl)로 팩터링하는 방법을 참조하세요.

클래스는 기본 클래스의 멤버를 상속합니다. 상속은 기본 클래스의 생성자를 제외하고 클래스에 기본 클래스의 모든 멤버를 암시적으로 포함한다는 것을 의미합니다. 파생된 클래스를 상속하는 대상에 새 멤버를 추가할 수 있지만 상속된 멤버의 정의를 제거할 수 없습니다.

이전 예제에서 볼륨영역높이너비 속성을 상속합니다. 따라서 모든 볼륨 인스턴스에는 높이, 너비깊이의 세 가지 속성이 포함됩니다.

일반적으로 형식 확인 규칙은 참조할 때 형식 이름을 정규화해야 합니다. 예외는 형식이 현재 형식과 동일한 네임스페이스에 정의된 경우입니다. 위의 예제는 영역볼륨 이 모두 동일한 네임스페이스에 있는 경우 작성된 대로 작동합니다.

구현된 인터페이스

클래스 정의는 클래스가 구현하는 인터페이스 목록을 지정할 수도 있습니다. (선택 사항) 기본 클래스 다음에 인터페이스를 쉼표로 구분된 인터페이스 목록으로 지정합니다.

아래 예제에서 Area 클래스는 IStringable 인터페이스를 구현합니다. 볼륨 클래스는IStringable 및 가상 IEquatable 인터페이스를 모두 구현합니다.

unsealed runtimeclass Area : Windows.Foundation.IStringable
{
    Area(Int32 width, Int32 height);
    Int32 Height;
    Int32 Width;
}

runtimeclass Volume : Area, Windows.Foundation.IStringable, IEquatable
{
    Volume(Int32 width, Int32 height, Int32 depth);
    Int32 Depth;
}

MIDL에서는 클래스에서 인터페이스의 멤버를 선언하지 않습니다. 물론 실제 구현에서 선언하고 정의해야 합니다.

멤버

클래스의 멤버는 정적 멤버 또는 인스턴스 멤버입니다. 정적 멤버는 클래스에 속합니다. 인스턴스 멤버는 개체(즉, 클래스의 인스턴스)에 속합니다.

이 표에서는 클래스에 포함될 수 있는 멤버의 종류를 보여 줍니다.

멤버 종류 설명
생성자 클래스의 인스턴스를 초기화하거나 클래스 자체를 초기화하는 데 필요한 작업
속성 클래스 인스턴스 또는 클래스 자체의 명명된 속성 읽기 및 쓰기와 관련된 작업
메서드 클래스의 인스턴스 또는 클래스 자체에서 수행할 수 있는 계산 및 작업
이벤트 클래스 인스턴스에서 발생할 수 있는 알림

생성자

MIDL 3.0은 인스턴스 생성자의 선언을 지원합니다. 인스턴스 생성자는 클래스의 인스턴스를 초기화하는 데 필요한 작업을 구현하는 메서드입니다. 생성자는 정적이지 않을 수 있습니다.

생성자는 인스턴스 메서드처럼 선언되고(반환 형식은 없음), 포함하는 클래스와 이름이 같습니다.

인스턴스 생성자는 오버로드될 수 있습니다. 예를 들어 아래 테스트 클래스는 세 개의 인스턴스 생성자를 선언합니다. 하나는 매개 변수가 없고( 기본 생성자), 하나는 Int32 매개 변수를 사용하고, 다른 하나는 두 개의 이중 매개 변수(매개 변수가 있는 생성자)를 사용합니다.

runtimeclass Test
{
    Test();
    Test(Int32 x);
    Test(Double x, Double y);
}

매개 변수 목록의 구문에 대한 자세한 내용은 아래 메서드를 참조하세요.

인스턴스 속성, 메서드 및 이벤트가 상속됩니다. 인스턴스 생성자는 상속되지 않으며(한 가지 예외를 제외하고) 클래스에는 클래스에 실제로 선언된 생성자 이외의 인스턴스 생성자가 없습니다. 클래스에 대해 제공된 인스턴스 생성자가 없는 경우 클래스를 직접 인스턴스화할 수 없습니다. 이러한 클래스의 경우 일반적으로 클래스의 인스턴스를 반환하는 팩터리 메서드가 다른 곳에 있습니다.

예외는 봉인되지 않은 클래스입니다. 봉인되지 않은 클래스에는 하나 이상의 보호된 생성자가 있을 수 있습니다.

속성

속성 은 개념적으로 필드(예: C# 필드 또는 MIDL 3.0 구조체의 필드)와 유사합니다. 속성과 필드는 모두 이름과 연결된 형식의 멤버입니다. 그러나 필드와 달리 속성은 스토리지 위치를 명시하지 않습니다. 대신 속성에는 속성을 읽거나 쓸 때 실행할 함수를 지정하는 접근 자가 있습니다.

선언이 키워드 및/또는 set 구분 기호 {와 }사이에 작성된 키워드로 끝나고 세미콜론으로 get 끝나는 것을 제외하고 속성은 구조체 필드처럼 선언됩니다.

키워드와 set 키워드가 get 모두 있는 속성은 읽기/쓰기 속성입니다. 키워드만 get 있는 속성은 읽기 전용 속성입니다. Windows 런타임 쓰기 전용 속성을 지원하지 않습니다.

예를 들어 이전에 본 클래스 영역HeightWidth라는 두 개의 읽기-쓰기 속성을 포함합니다.

unsealed runtimeclass Area
{
    Int32 Height { get; set; };
    Int32 Width; // get and set are implied if both are omitted.
}

Width 선언은 중괄호와 키워드를 getset 생략합니다. 생략은 속성이 읽기-쓰기이며 의미상 해당 순서setget로 키워드를 set 제공하는 get 것과 의미상 동일하다는 것을 의미합니다.

또한 키워드만 get 지정하여 속성이 읽기 전용임을 나타낼 수 있습니다.

// Read-only instance property returning mutable collection.
Windows.Foundation.Collections.IVector<Windows.UI.Color> Colors { get; };

Windows 런타임 쓰기 전용 속성을 지원하지 않습니다. 그러나 키워드만 set 지정하여 기존 읽기 전용 속성을 읽기/쓰기 속성으로 수정할 수 있습니다. 이 버전의 Area 를 예로 들어 하세요.

unsealed runtimeclass Area
{
    ...
    Color SurfaceColor { get; };
}

이후에 SurfaceColor 속성을 읽기/쓰기로 설정하려는 경우 영역의 이전 정의와 이진 호환성을 유지할 필요가 없는 경우(예: Area 클래스는 매번 다시 컴파일하는 애플리케이션의 형식임) 다음과 같이 기존 SurfaceColor 선언에 키워드를 추가할 set 수 있습니다.

unsealed runtimeclass Area
{
    ...
    Color SurfaceColor { get; set; };
}

반면에 이진 안정성 이 필요한 경우 (예: Area 클래스는 고객에게 제공하는 라이브러리의 구성 요소) 기존 속성 선언에 키워드를 추가할 set 수 없습니다. 이렇게 하면 이진 인터페이스가 클래스로 변경됩니다.

이 경우 다음과 같이 클래스의 끝에 있는 속성의 추가 정의에 속성 키워드를 추가 set 합니다.

unsealed runtimeclass Area
{
    ...
    Color SurfaceColor { get; };
    ...
    Color SurfaceColor { set; };
}

컴파일러는 쓰기 전용 속성에 대한 오류를 생성합니다. 하지만 그건 여기 무슨 일이 일어나고 있지 않다. 속성의 이전 선언이 읽기 전용이므로 set 키워드를 추가하면 쓰기 전용 속성이 아니라 읽기/쓰기 속성이 선언됩니다.

속성의 Windows 런타임 구현은 인터페이스에서 하나 또는 두 개의 접근자 메서드입니다. 속성 선언에서 get 및 set 키워드의 순서는 지원 인터페이스에서 get 및 set 접근자 메서드의 순서를 결정합니다.

접근 get 자가 속성 형식의 반환 값(속성 getter)이 있는 매개 변수가 없는 메서드에 해당합니다.

set 접근자가 명명된 단일 매개 변수 이 있고 반환 형식이 없는 메서드(속성 setter)에 해당합니다.

따라서 이러한 두 선언은 서로 다른 이진 인터페이스를 생성합니다.

Color SurfaceColor { get; set; };
Color SurfaceColor { set; get; };
정적 및 인스턴스 속성

메서드와 마찬가지로 MIDL 3.0은 인스턴스 속성과 정적 속성을 모두 지원합니다. 정적 속성은 접두사로 한정자를 사용하여 선언 static 되고 인스턴스 속성은 해당 속성 없이 선언됩니다.

메서드

메서드는 클래스의 인스턴스 또는 클래스 자체에서 수행할 수 있는 계산 또는 작업을 구현하는 멤버입니다. 정적 메서드는 클래스를 통해 액세스됩니다. 인스턴스 메서드는 클래스의 인스턴스를 통해 액세스됩니다.

메서드에는 메서드에 전달된 값 또는 변수 참조를 나타내는(비어 있는) 매개 변수 목록이 있습니다. 메서드에는 메서드에서 계산하고 반환하는 값의 형식을 지정하는 반환 형식도 있습니다. 메서드의 반환 형식은 값을 반환하지 않는 경우입니다 void .

// Instance method with no return value.
void AddData(String data);

// Instance method *with* a return value.
Int32 GetDataSize();

// Instance method accepting/returning a runtime class.
// Notice that you don't say "&" nor "*" for reference types.
BasicClass MergeWith(BasicClass other);

// Asynchronous instance methods.
Windows.Foundation.IAsyncAction UpdateAsync();
Windows.Foundation.IAsyncOperation<Boolean> TrySaveAsync();

// Instance method that returns a value through a parameter.
Boolean TryParseInt16(String input, out Int16 value);

// Instance method that receives a reference to a value type.
Double CalculateArea(ref const Windows.Foundation.Rect value);

// Instance method accepting or returning a conformant array.
void SetBytes(UInt8[] bytes);
UInt8[] GetBytes();

// instance method that writes to a caller-provided conformant array
void ReadBytes(ref UInt8[] bytes);

메서드의 시그니처는 메서드가 선언되는 클래스에서 고유해야 합니다. 메서드의 서명은 메서드의 이름, 해당 매개 변수의 형식 및/또는 해당 매개 변수의 수로 구성됩니다. 메서드 시그니처는 반환 형식을 포함하지 않습니다.

메서드 표시 유형 한정자

메서드가 파생 클래스에 있는 경우 메서드에 두 가지 선택적 표시 유형 한정자 중 하나가 있을 수 있습니다.

재정의 가능한 한정자는 이 메서드가 서브클래스에 속하는 메서드(이름과 시그니처가 같은)에 의해 재정의될 수 있음을 나타냅니다.

보호된 한정자에 따르면 이 메서드는 이후에 파생된 클래스의 멤버만 액세스할 수 있습니다.

메서드 오버로드

메서드 오버로드를 사용하면 동일한 클래스의 여러 메서드가 매개 변수의 개수가 다르면 동일한 이름을 가질 수 있습니다(즉, 메서드의 특성이 다른 경우).

runtimeclass Test
{
    static void F();
    static void F(Double x);
    static void F(Double x, Double y);
}

참고

이름이 같은 모든 메서드는 서로 다른 특성이 있어야 합니다. 약한 형식의 프로그래밍 언어는 형식별 오버로드를 지원하지 않기 때문입니다.

매개 변수

매개 변수 는 메서드에 값 또는 변수 참조를 전달하는 데 사용됩니다. 매개 변수는 형식과 이름이 있는 슬롯과 선택적으로 일부 한정자 키워드를 설명합니다. 인수는 메서드의 호출자에서 호출 수신자에게 해당 슬롯에 전달된 실제 값입니다.

메서드의 매개 변수는 메서드가 호출될 때 지정된 특정 인수 에서 해당 값을 가져옵니다. 호출자와 호출자 간에 인수가 전달되는 방식은 매개 변수의 형식에 따라 달라집니다. 기본적으로 모든 매개 변수는 입력 매개 변수입니다. 즉, 호출자에서 호출자로만 마샬링됩니다. 한정자 키워드를 refref constout 추가하고 호출자와 호출자 간의 마샬링의 기본 방향을 수정하고 출력 매개 변수를 만들 수 있습니다. 하지만 모든 매개 변수 형식에서 모든 키워드가 유효하지는 않습니다. 유효한 조합은 아래에 자세히 설명되어 있습니다.

중요

CLR(공용 언어 런타임)에는 이 섹션에 설명된 것과 유사한 개념 및 한정자 키워드가 있습니다. 그러나 실제로는 관련이 없으며 이러한 한정자의 효과는 Windows 런타임 디자인 및 작동과 관련이 있습니다.

값 형식은 암시적으로 입력 매개 변수이며, 기본적으로 인수의 복사본이 호출자에서 호출자에게 전달됩니다. 값 매개 변수는 키워드를 사용하여 out출력 매개 변수로 변환할 수 있습니다. 이 경우 인수는 호출 수신자에서 호출자로만 다시 마샬링됩니다.

runtimeclass Test
{
    static void Divide(Int32 x, Int32 y, out Int32 result, out Int32 remainder);
}

특수한 성능 최적화로, 일반적으로 값으로 전체 복사본으로 전달되는 구조체 형식(및 다른 형식은 없음)을 변경할 수 없는 구조체에 대한 포인터로 전달할 수 있습니다. 이는 구조체 매개 변수를 입력 매개 변수로 표시하는 (notconst ref) 키워드를 사용하여 수행 ref const 되지만, 구조체의 전체 복사본을 전달하는 대신 마샬러에게 구조체의 스토리지에 포인터를 전달하도록 지시합니다. 그러나 구조체는 변경할 수 없습니다. 포인터는 개념적으로 const 포인터입니다. 권투는 관여하지 않습니다. 예를 들어 Matrix4x4만큼 큰 값을 수락할 때는 이 옵션을 사용할 수 있습니다.

runtimeclass Test
{
    static Boolean IsIdentity(ref const Windows.Foundation.Numerics.Matrix4x4 m);
}

참조 형식은 암시적으로 입력 매개 변수이기도 합니다. 즉, 호출자가 개체를 할당하고 참조를 인수로 전달해야 합니다. 그러나 인수는 개체에 대한 참조이므로 호출자가 호출한 후 호출자가 해당 개체를 수정하는 것을 관찰합니다. 또는 참조 형식을 키워드로 출력 매개 변수로 out 만들 수 있습니다. 이 경우 역할은 반대로 바뀝니다. 호출 수신자는 개체를 할당하고 호출자에게 다시 반환하는 호출자입니다. 다시 말하지만, ref 키워드는 참조 형식과 함께 일반적으로 사용할 수 없습니다(아래 예외 참조).

runtimeclass Test
{
    static void CreateObjectWithConfig(Config config, out MyClass newObject);
}

다음 표에서는 값 매개 변수 및 참조 매개 변수에 대한 마샬링 키워드의 동작을 요약합니다.

동작 할당자 키워드 형식 설명
입력 매개 변수 Caller (없음) 모든 형식 기본 동작
ref const 구조체만 성능 최적화
출력 매개 변수 호출 수신자 out 모든 형식

Windows 런타임 매개 변수로서의 동작이 다소 다른 배열 형식을 지원합니다. 배열은 순차적으로 저장되고 인덱스를 통해 액세스되는 여러 변수를 포함하는 데이터 구조입니다. 배열의 요소 라고도 하는 배열에 포함된 변수는 모두 동일한 형식이며 이 형식을 배열의 요소 형식 이라고 합니다.

MIDL 3.0은 1 차원 배열의 선언을 지원합니다.

배열 매개 변수는 참조 형식이며 모든 참조 형식과 마찬가지로 기본적으로 입력 매개 변수입니다. 이 경우 호출자는 해당 요소를 읽을 수 있지만 수정할 수 없는 배열을 호출자에게 할당합니다(읽기 전용). 이를 통과 배열 패턴이라고 합니다. 또는 매개 변수에 키워드를 추가하여 ref채우기 배열 패턴을 사용할 수 있습니다. 이 설정에서 배열은 여전히 호출자에 의해 할당되지만 호출자가 배열 요소의 값을 채우도록 개념적으로 출력 매개 변수입니다. 마지막으로, 마지막 패턴은 호출자가 호출자에게 반환되기 전에 인수를 할당하고 초기화하는 수신 배열 (예: 모든 출력 참조 매개 변수)입니다.

runtimeclass Test
{
    // Pass array pattern: read-only array from caller to callee
    void PassArray(Int32[] values);

    // Fill array pattern: caller allocates array for callee to fill
    void FillArray(ref Int32[] values);

    // Receive array pattern: callee allocates and fill an array returned to caller
    void ReceiveArray(out Int32[] values);
}

다음 표에는 배열 및 해당 요소에 대한 동작이 요약되어 있습니다.

배열 패턴 키워드 할당자 호출 수신자별 요소 액세스
"배열 전달" (없음) Caller 읽기 전용
"배열 채우기" ref Caller 쓰기 전용
"배열 수신" out 호출 수신자 읽기/쓰기

C++/WinRT를 사용하여 C 스타일 배열 매개 변수(준수 배열이라고도 함)를 사용하는 방법에 대한 자세한 내용은 배열 매개 변수를 참조하세요.

정적 및 인스턴스 메서드

한정자 접두사로 static 선언된 메서드는 정적 메서드입니다. 정적 메서드는 특정 인스턴스에 액세스할 수 없으므로 클래스의 다른 정적 멤버에만 직접 액세스할 수 있습니다.

static 한정자를 사용하지 않고 선언된 메서드는 ‘인스턴스 메서드’입니다. 인스턴스 메서드는 특정 인스턴스에 액세스할 수 있으며 클래스의 정적 멤버와 인스턴스 멤버 모두에 액세스할 수 있습니다.

다음 Entity 클래스에는 정적 멤버와 인스턴스 멤버가 모두 있습니다.

runtimeclass Entity
{
    Int32 SerialNo { get; };
    static Int32 GetNextSerialNo();
    static void SetNextSerialNo(Int32 value);
}

엔터티 인스턴스에는 고유한 일련 번호(그리고 여기에 표시되지 않는 다른 정보)가 포함되어 있습니다. 내부적으로 엔터티 생성자(인스턴스 메서드와 같음)는 사용 가능한 다음 일련 번호로 새 인스턴스를 초기화합니다.

SerialNo 속성은 속성 get 메서드를 호출하는 인스턴스의 일련 번호에 대한 액세스를 제공합니다.

GetNextSerialNoSetNextSerialNo 정적 메서드는 Entity 클래스의 사용 가능한 내부 다음 일련 번호 정적 멤버에 액세스할 수 있습니다.

재정의 가능하고 보호된 메서드

Windows 런타임 형식의 모든 메서드는 사실상 가상입니다. 가상 메서드가 호출되면 호출이 발생하는 인스턴스의 런타임 형식에 따라 호출할 실제 메서드 구현이 결정됩니다.

파생 클래스에서 메서드를 재정 의할 수 있습니다. 인스턴스 메서드 선언에 한 overridable 정자가 포함된 경우 파생 클래스에서 메서드를 재정의할 수 있습니다. 파생 클래스가 실제로 재정의 가능한 기본 클래스 메서드를 재정의하는지 여부는 구현에 의해 결정됩니다. 메타데이터에 없습니다. 파생 클래스가 기본 클래스에서 메서드를 다시 선언하는 경우 재정의하는 대신 파생 클래스 메서드와 함께 배치되는 새 메서드를 선언합니다.

인스턴스 메서드 선언에 한정자가 포함된 protected 경우 메서드는 파생 클래스에만 표시됩니다.

이벤트

이벤트 선언은 클래스가 이벤트 원본임을 지정하는 멤버입니다. 이러한 이벤트 원본은 대리자(특정 서명이 있는 메서드)를 구현하는 받는 사람에게 알림을 제공합니다.

키워드를 event 사용하여 이벤트를 선언한 다음 대리자 형식 이름(필요한 메서드 서명을 설명함) 뒤에 이벤트의 이름을 지정합니다. 다음은 플랫폼에서 기존 대리자 형식을 사용하는 예제 이벤트입니다.

runtimeclass Area
{
    ...
    event Windows.UI.Xaml.WindowSizeChangedEventHandler SizeChanged;
    ...
}

이벤트 선언은 암시적으로 클래스에 두 가지 메서드를 추가합니다. 즉, 클라이언트가 소스에 이벤트 처리기를 추가하기 위해 호출하는 add 메서드와 이전에 추가한 이벤트 처리기를 제거하기 위해 클라이언트가 호출하는 remove 메서드입니다. 다음은 더 많은 예입니다.

// Instance event with no meaningful payload.
event Windows.Foundation.TypedEventHandler<BasicClass, Object> Changed;

// Instance event with event parameters.
event Windows.Foundation.TypedEventHandler<BasicClass, BasicClassSaveCompletedEventArgs> SaveCompleted;

// Static event with no meaningful payload.
static event Windows.Foundation.EventHandler<Object> ResetOccurred;

// Static event with event parameters.
static event Windows.Foundation.EventHandler<BasicClassDeviceAddedEventArgs> DeviceAdded;

규칙에 따라 두 매개 변수는 항상 Windows 런타임 이벤트 처리기에 전달됩니다. 즉, 보낸 사람의 ID와 이벤트 인수 개체입니다. 발신자는 이벤트를 발생시킨 개체이거나 정적 이벤트의 경우 null입니다. 이벤트에 의미 있는 페이로드가 없는 경우 이벤트 인수는 값이 null인 Object 입니다.

대리자

대리자 형식은 특정 매개 변수 목록 및 반환 형식이 있는 메서드를 지정합니다. 이벤트의 단일 인스턴스는 대리자 형식의 인스턴스에 대한 참조 수를 포함할 수 있습니다. 선언은 런타임 클래스 외부에 있고 키워드 접두사로 사용된다는 점을 제외하고 일반 멤버 메서드의 선언과 delegate 비슷합니다.

대리자를 사용하면 메서드를 변수에 할당하고 매개 변수로 전달할 수 있는 엔터티로 처리할 수 있습니다. 대리자는 다른 언어의 함수 포인터와 개념이 비슷하지만 그러나 함수 포인터와 달리 대리자는 개체 지향적이고 형식이 안전합니다.

플랫폼에서 WindowSizeChangedEventHandler 대리자 형식을 사용하지 않으려면 자체 대리자 형식을 정의할 수 있습니다.

delegate void SizeChangedHandler(Object sender, Windows.UI.Core.WindowSizeChangedEventArgs args);

SizeChangedHandler 대리자 형식의 인스턴스는 두 인수(ObjectWindowSizeChangedEventArgs)를 사용하고 void를 반환하는 모든 메서드를 참조할 수 있습니다. 구조체에 대해 설명한 후에는 WindowSizeChangedEventArgs 매개 변수를 사용자 고유의 이벤트 인수 형식으로 바꿀 수도 있습니다.

대리자의 흥미롭고 유용한 속성은 참조하는 메서드의 클래스를 모르거나 신경 쓰지 않는다는 것입니다. 중요한 것은 참조된 메서드에 대리자와 동일한 매개 변수 및 반환 형식이 있다는 것입니다.

필요에 따라 대리자 선언 [uuid(...)]에 특성을 지정할 수 있습니다.

HRESULT를 반환하는 대리자를 참조하세요.

구조체

구조체는 데이터 멤버(필드)를 포함할 수 있는 데이터 구조체입니다. 그러나 클래스와 달리 구조체는 값 형식입니다.

구조체는 값 의미 체계를 갖는 작은 데이터 구조에 특히 유용합니다. 복소수 또는 좌표계의 점이 구조체의 좋은 예입니다. 작은 데이터 구조체에 대한 클래스가 아닌 구조체를 사용하면 애플리케이션이 수행하는 메모리 할당 수에 큰 차이를 만들 수 있습니다.

예제를 사용하여 클래스와 구조체를 대조해 보겠습니다. 다음은 클래스첫 번째 Point 버전입니다.

runtimeclass Point
{
    Point(Int32 x, Int32 y);
    Int32 x;
    Int32 y;
}

이 C# 프로그램은 Point 인스턴스 100개 배열을 만들고 초기화합니다. Point가 클래스로 구현되면 배열 개체 자체에 대해 하나씩 101개의 개별 개체가 인스턴스화됩니다. 100개 점 요소 각각에 대해 하나씩

class Test
{
    static Test()
    {
        Point[] points = new Point[100];
        for (Int32 i = 0; i < 100; ++i) points[i] = new Point(i, i);
    }
}

보다 성능이 좋은 대안은 Point 를 클래스 대신 구조체로 만드는 것입니다.

struct Point
{
    Int32 x;
    Int32 y;
};

이제 배열 개체 자체인 하나의 개체만 인스턴스화됩니다. Point 요소는 배열 내부에 줄에 저장됩니다. 프로세서 캐시가 강력한 효과를 발휘하는 데 사용할 수 있는 메모리 정렬입니다.

구조체를 변경하는 것은 이진 호환성이 손상되는 변경입니다. 따라서 Windows 자체의 일부로 구현된 구조체는 일단 도입된 후에는 변경되지 않습니다.

인터페이스

인터페이스는 클래스에서 구현할 수 있는 계약을 정의합니다. 인터페이스는 클래스와 마찬가지로 메서드, 속성 및 이벤트를 포함할 수 있습니다.

클래스와 달리 인터페이스는 정의하는 멤버의 구현을 제공하지 않습니다. 인터페이스를 구현하는 모든 클래스에서 제공해야 하는 멤버만 지정합니다.

인터페이스에는 다른 인터페이스도 구현하기 위해 인터페이스를 구현하는 클래스가 필요할 수 있습니다. 다음 예제에서 인터페이스 IComboBox를 사용하려면 IComboBox를 구현하는 모든 클래스가 ITextBoxIListBox를 모두 구현해야 합니다. 또한 IComboBox 를 구현하는 클래스도 IControl을 구현해야 합니다. ITextBoxIListBox 모두 필요하기 때문입니다.

interface IControl
{
    void Paint();
}

interface ITextBox requires IControl
{
    void SetText(String text);
}

interface IListBox requires IControl
{
    void SetItems(String[] items);
}

interface IComboBox requires ITextBox, IListBox
{
    ...
}

클래스는 0개 이상의 인터페이스를 구현할 수 있습니다. 다음 예제에서 EditBox 클래스는 IControlIDataBound를 모두 구현합니다.

interface IDataBound
{
    void Bind(Binder b);
}

runtimeclass EditBox : IControl, IDataBound
{
}

Windows 플랫폼의 Windows 런타임 형식의 경우 이러한 형식을 사용하는 개발자가 인터페이스를 구현해야 하는 경우 인터페이스가 정의됩니다. 인터페이스를 정의하기 위한 또 다른 사용 사례는 여러 런타임 클래스가 인터페이스를 구현하고 해당 런타임 클래스를 사용하는 개발자가 해당 공통 인터페이스를 통해 여러 유형의 개체에 일반적으로(따라서 다형적으로) 액세스하는 경우입니다.

참고

MIDL 3.0에서 키워드를 requires 사용하는 방법을 두 번 생각해 보세요. 특히 버전 관리가 고려될 때 지저분한 디자인으로 이어질 수 있습니다.

열거형

열거형 형식(또는 열거형 형식 또는 열거형)은 명명된 상수 집합이 있는 고유 값 형식입니다. 다음 예제에서는 세 가지 상수 값인 빨강, 녹색파랑을 사용하여 Color라는 열거형 형식을 정의하고 사용합니다.

enum Color
{
    Red,
    Green,
    Blue, // Trailing comma is optional, but recommended to make future changes easier.
};

각 열거형 형식에는 열거형 형식의 기본 형식 이라는 해당 정수 형식이 있습니다. 열거형의 기본 형식은 Int32 또는 UInt32입니다.

Windows 런타임 두 종류의 열거형, 즉 일반 열거형과 플래그 열거형을 지원합니다. 일반 종류의 열거형은 배타적 값 집합을 나타냅니다. 플래그 종류 중 하나가 부울 값 집합을 나타내는 동안 플래그 열거형에 비트 연산자를 사용하도록 설정하기 위해 MIDL 3.0 컴파일러는 C++ 연산자 오버로드를 생성합니다.

플래그 열거형에는 특성이 [flags] 적용됩니다. 이 경우 열거형의 기본 형식은 UInt32입니다. 특성이 [flags] 없는 경우(일반 열거형), 열거형의 기본 형식은 Int32입니다. 열거형을 다른 형식으로 선언할 수 없습니다.

[flags]
enum SetOfBooleanValues
{
    None   = 0x00000000,
    Value1 = 0x00000001,
    Value2 = 0x00000002,
    Value3 = 0x00000004,
};

열거형 형식의 스토리지 형식 및 가능한 값의 범위는 기본 형식에 따라 결정됩니다. 열거형 형식이 사용할 수 있는 값 집합은 선언된 열거형 멤버에 의해 제한되지 않습니다.

다음 예제에서는 Int32의 기본 형식을 사용하여 Alignment이라는 열거형 형식을 정의합니다.

enum Alignment
{
    Left = -1,
    Center = 0,
    Right = 1
};

C 및 C++의 경우와 마찬가지로 MIDL 3.0 열거형에는 위에서 볼 수 있듯이 멤버의 값을 지정하는 상수 식이 포함될 수 있습니다. 각 열거형 멤버의 상수 값은 열거형의 기본 형식 범위에 있어야 합니다. 열거형 멤버 선언에서 값을 명시적으로 지정하지 않으면 멤버에 값 0(열거형 형식의 첫 번째 멤버인 경우) 또는 텍스트 앞에 오는 열거형 멤버의 값과 1이 지정됩니다.

다음 예제에서는 기본 형식의 UInt32사용하여 Permissions라는 열거형 형식을 정의합니다.

[flags]
enum Permissions
{
    None = 0x0000,
    Camera = 0x0001,
    Microphone = 0x0002
};

특성

MIDL 3.0 소스 코드의 형식, 멤버 및 기타 엔터티는 동작의 특정 측면을 제어하는 한정자를 지원합니다. 예를 들어 메서드의 접근성은 액세스 한정자를 사용하여 protected 제어됩니다. MIDL 3.0은 사용자 정의 유형의 선언적 정보를 프로그램 엔터티에 연결하고 메타데이터에서 런타임에 검색할 수 있도록 이 기능을 일반화합니다.

프로그램은 특성을 정의하고 사용하여 이러한 추가적인 선언적 정보를 지정합니다.

다음 예제에서는 연결된 설명서에 대한 링크를 제공하기 위해 프로그램 엔터티에 배치할 수 있는 HelpAttribute 특성을 정의합니다. 보듯이 특성은 기본적으로 구조체 형식이므로 생성자가 없고 데이터 멤버만 포함합니다.

[attributeusage(target_runtimeclass, target_event, target_method, target_property)]
attribute HelpAttribute
{
    String ClassUri;
    String MemberTopic;
}

연결된 선언 바로 앞에 대괄호 안에 인수와 함께 해당 이름을 지정하여 특성을 적용할 수 있습니다. 특성의 이름이 특성으로 끝나는 경우 특성이 참조될 때 이름의 해당 부분을 생략할 수 있습니다. 예를 들어 HelpAttribute 특성은 다음과 같이 사용할 수 있습니다.

[Help("https://docs.contoso.com/.../BookSku", "BookSku class")]
runtimeclass BookSku : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
    [Help("https://docs.contoso.com/.../BookSku_Title", "Title method")]
    String Title;
}

특성 다음에 있는 범위 블록을 사용하여 여러 선언에 동일한 특성을 적용할 수 있습니다. 즉, 특성 바로 뒤에 특성이 적용되는 선언을 둘러싼 중괄호가 뒤따릅니다.

runtimeclass Widget
{
    [Help("https://docs.contoso.com/.../Widget", "Widget members")]
    {
        void Display(String text);
        void Print();
        Single Rate;
    }
}

Windows 자체의 일부로 구현되는 특성은 일반적으로 Windows.Foundation 네임스페이스에 있습니다.

첫 번째 예제와 같이 특성 정의에 [attributeusage(<target>)] 특성을 사용합니다. 유효한 대상 값은 target_all, target_delegate,, target_eventtarget_enum,target_fieldtarget_interface, target_method, target_parameter, target_propertytarget_runtimeclass및 입니다.target_struct 괄호 안에 여러 대상을 쉼표로 구분하여 포함할 수 있습니다.

특성에 적용할 수 있는 다른 특성은 다음과 같습니다 [allowmultiple][attributename("<name>")].

매개 변수화된 형식

아래 예제에서는 오류 MIDL2025를 생성합니다. [msg]구문 오류 [context]: 예상 > 또는 ">>"에 가깝습니다.

Windows.Foundation.IAsyncOperation<Windows.Foundation.Collections.IVector<String>> RetrieveCollectionAsync();

대신 템플릿 닫는 문자 쌍이 오른쪽 시프트 연산자로 잘못 해석되지 않도록 두 > 문자 사이에 공백을 삽입합니다.

Windows.Foundation.IAsyncOperation<Windows.Foundation.Collections.IVector<String> > RetrieveCollectionAsync();

아래 예제에서는 오류 MIDL2025를 생성합니다. [msg]구문 오류 [context]: 예상 > 또는 "["에 가깝습니다. 이는 매개 변수가 있는 인터페이스에 대한 매개 변수 형식 인수로 배열을 사용하는 것이 잘못되었기 때문입니다.

Windows.Foundation.IAsyncOperation<Int32[]> RetrieveArrayAsync();

솔루션은 비동기적으로 배열 반환을 참조하세요.