Microsoft インターフェイス定義言語 3.0 の概要

Microsoft Interface Definition Language (MIDL) 3.0 は、インターフェイス定義言語 (IDL) ファイル (.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 内で開発されました。 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\winrt Windows SDK フォルダーを見ると、MIDL 2.0 構文で記述された .idl ファイルの例が表示されます。 これらは組み込みの Windows ランタイム API であり、アプリケーション バイナリ インターフェイス (ABI) 形式で宣言されています。 これらのファイルは主にツールで使用するために存在します。この形式でこれらの 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 ランタイム API との間で Windows ランタイム型を排他的に渡すように選択することで行われます。 Windows ランタイム API との間で生の COM インターフェイスを渡すことが有効な設計上の決定ですが、これを行うと、その特定の Windows ランタイム API のコンシューマーが C++ アプリケーションに制限されます。 この手法は、相互運用シナリオ (Direct3D と XAML の間で相互運用する場合など) で確認できます。 Direct3D は図に含まれているので、シナリオは必ずしも C++ アプリケーションに絞り込まれます。 そのため、COM インターフェイスを必要とする API では、固有の制限以上の制限は課されません。 たとえば、C++ アプリケーションでは、IDXGISwapChain インターフェイス ポインターを取得し、それを ISwapChainPanelNative::SetSwapChain メソッドに渡すことができます。 たとえば、C# アプリケーションでは、最初に IDXGISwapChain を取得できないため、その理由でそのメソッドを使用することはできません。 これらの相互運用関連の例外は、windows.ui.xaml.media.dxinterop.hなどの相互運用ヘッダーで実行されます。

C++ 以外の Windows ランタイム言語プロジェクションに公開する COM コンポーネントの機能 場合は、C++ Windows ランタイム コンポーネント (WRC) を作成し、COM コンポーネント (DirectX など) を直接作成して使用し、Windows ランタイム API サーフェイスの形式で機能のサブセットのレプリケーションを公開できます。ランタイム型のみ。 その後、 Windows ランタイム言語プロジェクション 記述されたアプリケーションからその WRC を使用できます。

定義構造とコマンド ラインからの midl.exe の呼び出し

MIDL 3.0 定義の主要な組織の概念は、名前空間、型、およびメンバーです。 MIDL 3.0 ソース ファイル (.idl ファイル) には少なくとも 1 つの名前空間が含まれており、その中には型や下位の名前空間があります。 各型には、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 インターフェイス 実装します。 また、このクラスには、2 つのコンストラクター、読み取り/書き込みプロパティ (Price)、読み取り専用プロパティ (Titleを介した AuthorName)、および 2 つのメソッド (Equals と ApplyDiscount) が含まれています。 floatではなく、単一 使用されることに注意してください。 そして、文字列 は大文字の "S"を持っています。

先端

Visual Studio は、C++/WinRT Visual Studio Extension (VSIX) を使用して MIDL 3.0 をコンパイルするための最適なエクスペリエンスを提供します。 C++/WinRT Visual Studio のサポートと VSIXに関するページを参照してください。

ただし、コマンド ラインから 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 ファイルをすべて、ルート名前空間と同じ名前の 1 つのファイルにマージします。 最終的な .winmd ファイルは、API のコンシューマーが参照するファイルになります。

この場合、bookSku は、Bookstore 名前空間の唯一のランタイム クラスであるため、ステップを保存し、名前空間の ファイルという名前を付けただけです。

なお、where コマンドを使用して、midl.exe がインストールされている場所を確認できます。

where midl

別の .idl ファイルの 1 つの .idl ファイルで定義されている型を使用する場合は、import ディレクティブを使用します。 詳細とコード例については、XAML コントロール 参照してください。C++/WinRT プロパティにバインドします。 もちろん、組み込みコンポーネントまたはサード パーティ製コンポーネントを使用している場合は、.idl ファイルにアクセスできません。 たとえば、Win2D Windows ランタイム API を使用して、イミディエイト モードの 2D グラフィックス レンダリングを行うことができます。 上記のコマンドでは、/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 クラスを宣言する 2 つの方法です (ご覧のとおり、ピリオドは入れ子になった名前空間のレベルを区切ります)。

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 には、値型と参照型の 2 種類のデータ型があります。 値型の変数には、そのデータが直接含まれています。 参照型の変数は、そのデータへの参照を格納します (このような変数は、オブジェクトとも呼ばれます)。

2 つの参照型変数で同じオブジェクトを参照できます。 したがって、1 つの変数に対する操作は、もう一方の変数によって参照されるオブジェクトに影響します。 値型では、変数にはそれぞれデータのコピーがあり、一方の操作がもう一方に影響を与えることはできません。

MIDL 3.0 の値型は、さらに単純型、列挙型、構造体型、および null 許容型に分割されます。

MIDL 3.0 の参照型は、さらにクラス型、インターフェイス型、デリゲート型に分割されます。

MIDL 3.0 の型システムの概要を次に示します。 以前のバージョンの MIDL とは異なり、これらの型にはエイリアスを使用できません。

カテゴリ 形容
値型 単純型 符号付き整数: Int16, Int32, Int64
符号なし整数: UInt8UInt16UInt32UInt64
Unicode 文字: Char (UTF-16LE、16 ビット Unicode コード単位を表します)
Unicode 文字列: 文字列
IEEE 浮動小数点: SingleDouble
Boolean: Boolean
128 ビット UUID: Guid
列挙型 フォームのユーザー定義型 列挙型 E {...}
構造体の型 構造体 S {...} フォームのユーザー定義型
Null 許容型 null 値を持つ他のすべての値型の拡張
参照型 クラス型 他のすべての型の Ultimate 基底クラス: Object
ランタイム クラス C {...} フォームのユーザー定義型
インターフェイスの種類 フォームのユーザー定義型 インターフェイス I {...}
デリゲート型 フォームのユーザー定義型 デリゲート <returnType> D(...)

7 つの整数型は、8 ビット符号なしデータをサポートします。符号付きまたは符号なし形式の 16 ビット、32 ビット、64 ビットの値。

2 つの浮動小数点型 単精度倍精度は、それぞれ 32 ビットの単精度と 64 ビットの倍精度 IEEE 754 形式を使用してデータを表します。

MIDL 3.0 の ブール 型はブール値を表します。true または false

MIDL 3.0 の文字と文字列には Unicode 文字が含まれています。 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 ダブル 5.0 × 10-324 から 1.7 × 10308、15 桁の精度

MIDL 3.0 ソース ファイルでは、型定義を使用して新しい型を作成します。 型定義では、新しい型の名前とメンバーを指定します。 これらの MIDL 3.0 型のカテゴリは、ユーザー定義可能です。

  • 属性の型、
  • 構造体の型
  • インターフェイスの種類、
  • runtimeclass 型、
  • デリゲート型、および
  • 列挙型。

属性 型は、他の型定義に適用できる Windows ランタイム属性を定義します。 属性は、属性が適用される型に関するメタデータを提供します。

構造体 型は、データ メンバー (フィールド) を含む Windows ランタイム構造体を定義します。 構造体は値型であり、ヒープ割り当てを必要としません。 構造体型のデータ メンバーは、値型または null 許容型である必要があります。 構造体型は継承をサポートしていません。

インターフェイス 型は、関数メンバーの名前付きセットである Windows ランタイム インターフェイスを定義します。 インターフェイスは、インターフェイスの実装で、指定された 1 つ以上の追加 (必須) インターフェイスも実装する必要があることを指定できます。 すべてのインターフェイスの種類は、Windows ランタイム IInspectable インターフェイスから直接派生します。

ランタイムクラス 型は、Windows ランタイム クラス (ランタイム クラス) を定義します。 ランタイム クラスには、プロパティ、メソッド、およびイベントを指定できるメンバーが含まれています。

デリゲート 型は、特定のパラメーター リストと戻り値の型を持つメソッドへの参照を表す Windows ランタイム デリゲートを定義します。 デリゲートを使用すると、メソッドをパラメーターとして渡すことができるエンティティとして扱うことができます。 デリゲートは、他の言語で見つかる関数ポインターの概念に似ています。 関数ポインターとは異なり、デリゲートはオブジェクト指向であり、型セーフです。

列挙型 型は、名前付き定数を持つ個別の型です。 すべての列挙型には暗黙的な基になる型があります。Int32 または UInt32を します。 列挙型の値のセットは、基になる型の値のセットと同じです。

MIDL 3.0 では、追加の 3 種類のカテゴリがサポートされています。

  • 1 次元配列型、
  • null 許容値型、および
  • オブジェクト 型。

使用する前に、1 次元配列を宣言する必要はありません。 代わりに、配列型は、角かっこで囲まれた型名に従って構築されます。 たとえば、Int32[] は、Int32の 1 次元配列です。

同様に、null 許容 値型も、使用する前に定義する必要はありません。 (文字列を除 く) T 非 null 許容値の型ごとに、Windows.Foundation.IReferenceT対応する null 許容型があり、追加の値 を保持できます。 たとえば、Windows.Foundation.IReference<Int32> は、任意の 32 ビット整数または値 nullを保持できる型です。 IReferenceTも参照してください。

最後に、MIDL 3.0 では、Windows ランタイム IInspectable インターフェイスにマップされる Object 型がサポートされています。 インターフェイスランタイムクラス 参照型は、概念的には Object 型から派生します。デリゲート しません。

列挙値の式

MIDL 3.0 では、列挙型の名前付き定数の値の定義に 式のみを使用できます。つまり、列挙初期化子です。

式は、オペランド および 演算子から構築されます。 式の演算子は、オペランドに適用する演算を示します。 演算子の例としては、+、-、*、/、および newがあります。 オペランドの例としては、リテラル、フィールド、ローカル変数、および式があります。

式に複数の演算子が含まれている場合、演算子の 優先順位 によって、個々の演算子の評価順序が制御されます。 たとえば、式 x + y * z は x + (y * z) として評価されます。これは、* 演算子が + 演算子よりも優先順位が高いためです。 論理演算は、ビットごとの演算よりも優先順位が低くなります。

次の表は、MIDL 3.0 の演算子をまとめたものです。演算子のカテゴリは、優先順位の高い順に一覧表示されます。 同じカテゴリの演算子の優先順位は同じです。

カテゴリ 表現 形容
原発 x++ インクリメント後
x-- デクリメント後
単項 +x 同一性
-x 否定
!x 論理否定
~x ビットごとの否定
++x 事前インクリメント
--x 事前デクリメント
乗算 x * y 掛け算
x / y 除法
x % y 剰余
添加物 x + y 加算、文字列連結、デリゲートの組み合わせ
x – y 減算、デリゲートの削除
動く 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 の型の最も基本的なものです。 クラスは、メソッド、プロパティ、およびイベントを 1 つの単位で集計する定義です。 クラスは 継承ポリモーフィズムをサポートします。派生クラス 基底クラス拡張および特殊化できるメカニズムです。

クラス定義を使用して、新しいクラス型を定義します。 クラス定義は、runtimeclass キーワード、クラスの名前、基底クラス (指定されている場合)、およびクラスによって実装されるインターフェイスを指定するヘッダーで始まります。 ヘッダーの後に、区切り記号 { と }の間に書き込まれたメンバー宣言のリストで構成されるクラス本体が続きます。

Areaという名前の単純なクラス 定義を次に示します。

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

    Int32 Height;
    Int32 Width;

    static Int32 NumberOfAreas { get; };
}

これにより、Areaという名前の新しい Windows ランタイム クラスが定義されます。このクラスには、2 つの Int32 パラメーターを受け取るコンストラクター、HeightWidthという名前の読み取り/書き込みプロパティ 2 つの Int32、および NumberOfAreasという名前 静的読み取り専用プロパティがあります。

既定では、ランタイム クラスはシールされ、そこからの派生は許可されません。 基底クラス を参照してください。

XAML をビュー モデルにバインドするには、ビュー モデル ランタイム クラスを MIDL で定義する必要があります。 XAML コントロール 参照してください。詳細については、 C++/WinRT プロパティにバインドします。

ランタイム クラス定義の前に static キーワードを付けることで、クラスでインスタンスがサポートされていないことを宣言できます (したがって、静的メンバーのみを含める必要があります)。 クラスに非静的メンバーを追加すると、コンパイル エラーが発生します。

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

静的クラスは空のクラスとは異なります。 空のクラス も参照してください。

ランタイム クラス定義の前に partial キーワードを付けることで、クラス定義が不完全であることを示すことができます。 コンパイラによって検出されるすべての部分クラス定義は、1 つのランタイム クラスに結合されます。 この機能は主に、部分的なクラスの一部がマシンで生成される XAML 作成シナリオ用です。

修飾子 意味
静的 クラスにはインスタンスがありません。 その結果、静的メンバーのみが許可されます。
パーシャル クラス定義が不完全です。

高度な修飾子については、「コンポジションとアクティブ化の」を参照してください。

メンバー アクセス修飾子

MIDL 3.0 は Windows ランタイム型のパブリック サーフェスを記述するための定義言語であるため、メンバーのパブリック アクセシビリティを宣言するための明示的な構文は必要ありません。 すべてのメンバーは暗黙的にパブリックです。 そのため、MIDL 3.0 では 、(実質的に冗長な) public キーワードは必要ありません。

基底クラス

クラス定義では、クラス名と型パラメーターにコロンと基底クラスの名前を付けて、基底クラスを指定できます。 基底クラスの指定を省略することは、オブジェクト 型 (つまり、IInspectableから ) から派生する場合と同じです。

手記

ビュー モデル クラス (実際には、アプリケーションで定義するランタイム クラス) は、基底クラスから派生する必要はありません。

基底クラスから派生 アプリケーションで定義するランタイム クラスは、コンポーザブル クラスと呼ばれます。 また、コンポーザブル クラスには制約があります。 アプリケーションが Visual Studio と Microsoft Store が提出を検証するために使用する Windows アプリ認定キット テストに合格するには (したがって、アプリケーションが Microsoft Store に正常に取り込まれるには)、最終的に Windows 基本クラスから派生する必要があります。 つまり、継承階層のルートにあるクラスは、Windows.* 名前空間から生成される型である必要があります。

XAML コントロール 参照してください。詳細については、 C++/WinRT プロパティにバインドします。

次の例では、Volume の基底クラスは領域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)に組み込む」を参照してください。

クラスは、その基底クラスのメンバーを継承します。 継承とは、基底クラスのコンストラクターを除き、基底クラスのすべてのメンバーがクラスに暗黙的に含まれていることを意味します。 派生クラスは、継承するメンバーに新しいメンバーを追加できますが、継承されたメンバーの定義を削除することはできません。

前の例では、Volume は、領域から Height プロパティと Width プロパティ 継承します。 そのため、すべての Volume インスタンスには、高さ深度の 3 つのプロパティが含まれます。

一般に、型解決規則では、参照時に型名を完全修飾する必要があります。 例外は、型が現在の型と同じ名前空間で定義されている場合です。 上の例は、AreaVolume の両方が同じ名前空間にある場合に記述されているように動作します。

実装されたインターフェイス

クラス定義では、クラスが実装するインターフェイスの一覧を指定することもできます。 (省略可能) 基底クラスに続くインターフェイスのコンマ区切りリストとしてインターフェイスを指定します。

次の例では、Area クラスは IStringable インターフェイスを実装しています。Volume クラスは、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 では、インスタンス コンストラクターの宣言がサポートされています。 インスタンス コンストラクター は、クラスのインスタンスを初期化するために必要なアクションを実装するメソッドです。 コンストラクターは静的でない場合があります。

コンストラクターは、インスタンス メソッドのように (ただし、戻り値の型を持たない) 、および包含クラスと同じ名前で宣言されます。

インスタンス コンストラクターはオーバーロードできます。 たとえば、以下の Test クラスでは、3 つのインスタンス コンストラクターが宣言されています。1 つはパラメーターを持たない (既定の コンストラクター)、1 つは Int32 パラメーターを受け取り、1 つは 2 つの Double パラメーター (パラメーター化された コンストラクター) を受け取ります。

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

パラメーター リストの構文の詳細については、以下の メソッドを参照してください。

インスタンスのプロパティ、メソッド、およびイベントは継承されます。 インスタンス コンストラクターは継承されず (1 つの例外を除く)、クラスには、クラスで実際に宣言されているもの以外のインスタンス コンストラクターはありません。 クラスにインスタンス コンストラクターが指定されていない場合、クラスを直接インスタンス化することはできません。 このようなクラスの場合、通常はクラスのインスタンスを返すファクトリ メソッドが他の場所にあります。

例外は封印されていないクラスです。 封印されていないクラスには、1 つ以上の保護されたコンストラクターを含めることができます。

プロパティ

プロパティ は、概念的にはフィールド (C# フィールドや MIDL 3.0 構造体のフィールドなど) に似ています。 プロパティとフィールドはどちらも、名前と関連付けられた型を持つメンバーです。 ただし、フィールドとは異なり、プロパティはストレージの場所を示していません。 代わりに、プロパティには、プロパティの読み取りまたは書き込み時に実行する関数を指定する アクセサーがあります。

プロパティは構造体のフィールドと同様に宣言されます。ただし、宣言は、区切り記号 { と }の間に書き込まれた get キーワードや set キーワードで終わり、セミコロンで終わる点を除きます。

get キーワードと set キーワードの両方を持つプロパティは、読み取り/書き込みプロパティです。 get キーワードのみを持つプロパティは、読み取り専用プロパティです。 Windows ランタイムでは、書き込み専用プロパティはサポートされていません。

たとえば、前に示した Area クラスには、Height と Widthという名前の 2 つの読み取り/書き込みプロパティ 含まれています。

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

Width の宣言では、中かっこ、get、および set キーワードは省略されます。 省略は、プロパティが読み取り/書き込みであり、その順序で get キーワードと set キーワードを指定するのと意味的に同じであることを意味します(get、その後に set

さらに、プロパティが読み取り専用であることを示す 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 の以前の定義 (たとえば、Area クラスは、毎回再コンパイルするアプリケーションの型) とのバイナリ互換性を維持する必要がない場合は、次のように既存の SurfaceColor 宣言に set キーワードを追加するだけです。

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

一方、バイナリの安定性 必要 場合 (たとえば、Area クラスは、顧客に出荷するライブラリ内のコンポーネントです)、既存のプロパティ宣言に キーワードを追加することはできません。 これにより、バイナリ インターフェイスがクラスに変更されます。

その場合は、次のように、プロパティ set キーワードをクラスの末尾にあるプロパティの追加定義に追加します。

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

コンパイラは、書き込み専用プロパティのエラーを生成します。 しかし、それはここで行われているものではありません。 前述のプロパティの宣言が読み取り専用であるため、set キーワードを追加しても、書き込み専用プロパティは宣言されませんが、代わりに読み取り/書き込みプロパティが宣言されます。

プロパティの Windows ランタイムの実装は、インターフェイス上の 1 つまたは 2 つのアクセサー メソッドです。 プロパティ宣言の get キーワードと set キーワードの順序によって、バッキング インターフェイスの get アクセサー メソッドと set アクセサー メソッドの順序が決まります。

get アクセサーは、プロパティ型 (プロパティ ゲッター) の戻り値を持つパラメーターなしのメソッドに対応します。

set アクセサーは、という名前の 1 つのパラメーターを持つメソッドに対応し、戻り値の型 (プロパティ セッター) はありません。

したがって、これら 2 つの宣言では、異なるバイナリ インターフェイスが生成されます。

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);

メソッドの シグネチャ は、メソッドが宣言されているクラスで一意である必要があります。 メソッドのシグネチャは、メソッドの名前、そのパラメーターの型、およびそのパラメーターの数で構成されます。 メソッドのシグネチャには、戻り値の型は含まれません。

メソッドの可視性修飾子

メソッド メソッドが派生クラスに存在する場合、オプションの可視性修飾子が 2 つのいずれかである場合があります。

オーバーライド可能な 修飾子は、サブクラスに属するメソッド (同じ名前とシグネチャを持つ) によってこのメソッドがオーバーライドされる可能性があることを示しています。

保護された 修飾子は、このメソッドは、後続の派生クラスのメンバーのみがアクセス可能であることを示します。

メソッドのオーバーロード

メソッド オーバーロード では、パラメーターの数が異なる限り、同じクラス内の複数のメソッドが同じ名前を持つことができます (つまり、メソッドの アリティが異なります)。

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

手記

同じ名前のすべてのメソッドは、アリティ異なる必要があります。 これは、弱く型指定されたプログラミング言語では、型によるオーバーロードがサポートされていないためです。

パラメーター

パラメーター は、値または変数参照をメソッドに渡すために使用されます。 パラメーター は、型と名前を持つスロットと、必要に応じて修飾子キーワードを記述します。 引数 は、メソッドの呼び出し元から呼び出し先にスロットに渡される実際の値です。

メソッドのパラメーターは、メソッドの呼び出し時に指定された特定の 引数 から値を取得します。 呼び出し元と呼び出し先の間で引数を渡す方法は、パラメーターの型によって異なります。 既定では、すべてのパラメーターは入力パラメーター されます。つまり、呼び出し元から呼び出し先にのみマーシャリングされます。 修飾子キーワード 、および を追加して、呼び出し元と呼び出し先の間のマーシャリングの既定の方向を変更し、出力パラメーター 作成できます。 ただし、すべてのキーワードがすべてのパラメーター型で有効なわけではありません。有効な組み合わせを以下に詳しく示します。

大事な

共通言語ランタイム (CLR) には、このセクションで説明されているものと似ているように見える概念と修飾子キーワードがあります。 ただし、実際にはこれらは関係なく、これらの修飾子の効果は Windows ランタイムの設計と機能に固有です。

値型は暗黙的に入力パラメーターされ、既定では、引数のコピーが呼び出し元から呼び出し先に渡されます。 値パラメーターは、 キーワードを使用して 出力パラメーターに変換できます。その場合、引数は代わりに呼び出し先から呼び出し元にのみマーシャリングされます。

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

特別なパフォーマンス最適化として、通常は値によって完全コピーとして渡される構造体型 (および他の型なし) は、変更できない構造体へのポインターによって渡されるようにすることができます。 これは、構造体パラメーターを入力パラメーターとしてマークする ref const (const refではない) キーワードを使用して実現されますが、構造体の完全なコピーを渡す代わりに、構造体のストレージへのポインターを渡すようにマーシャラーに指示します。 ただし、構造体は不変であることに注意してください。ポインターは概念的には 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);
}

次の表は、値パラメーターと参照パラメーターのマーシャリング キーワードの動作をまとめたものです。

振舞い 割り当て者 キーワード 種類 備考
入力パラメーター 来客 (なし) すべての型 既定の動作
ref const 構造体のみ パフォーマンスの最適化
出力パラメーター 呼び出し先 out すべての型

Windows ランタイムでは、パラメーターとしての動作が多少異なる配列型がサポートされています。 配列 は、連続して格納され、インデックスを介してアクセスされる多数の変数を含むデータ構造です。 配列に含まれる変数 (配列の 要素とも呼ばれます) はすべて同じ型であり、この型は配列の 要素型と呼ばれます。

MIDL 3.0 では、1 次元配列の宣言がサポートされています。

配列パラメーター は参照型であり、すべての参照型が既定で入力パラメーターと同様です。 その場合、呼び出し元は配列を呼び出し先に割り当てます。この配列は要素を読み取ることができますが、変更することはできません (読み取り専用)。 これは、配列 パターンを渡す と呼ばれます。 または、パラメーターに ref キーワードを追加することで、fill 配列 パターンを使用することもできます。その設定では、配列は呼び出し元によって引き続き割り当てられますが、概念的には、呼び出し先が配列要素の値を埋めるという意味での出力パラメーターです。 最後のパターンは、呼び出し先が呼び出し元に返される前に、呼び出し先が引数を割り当て、初期化している、配列を受け取る です。

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);
}

次の表は、配列とその要素の動作をまとめたものです。

配列パターン キーワード 割り当て者 呼び出し先による要素のアクセス
"配列を渡す" (なし) 来客 読み取り専用
"配列の塗りつぶし" ref 来客 書き込み専用
"配列の受信" out 呼び出し先 読み取り/書き込み

C++/WinRT で C スタイルの配列パラメーター (準拠配列とも呼ばれます) を使用する方法の詳細については、「配列パラメーターを参照してください。

静的メソッドとインスタンス メソッド

プレフィックスが付いた static 修飾子で宣言されたメソッドは、静的メソッドです。 静的メソッドは特定のインスタンスにアクセスできないため、クラスの他の静的メンバーにのみ直接アクセスできます。

修飾子なしで宣言されたメソッドは、インスタンス メソッドです。 インスタンス メソッドは、特定のインスタンスにアクセスでき、クラスの静的メンバーとインスタンス メンバーの両方にアクセスできます。

次の Entity クラスには、静的メンバーとインスタンス メンバーの両方があります。

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

Entity インスタンスには、独自のシリアル番号 (およびおそらくここには示されていないその他の情報) が含まれています。 内部的には、Entity コンストラクター (インスタンス メソッドのようなもの) は、次に使用可能なシリアル番号を使用して新しいインスタンスを初期化します。

SerialNo プロパティは、プロパティ get メソッドを呼び出すインスタンスのシリアル番号 アクセスできます。

GetNextSerialNo および SetNextSerialNo 静的メソッドは、Entity クラスの静的メンバー、次に使用可能な内部 シリアル番号にアクセスできます。

オーバーライド可能なメソッドと保護されたメソッド

Windows ランタイム型のすべてのメソッドは実質的に仮想です。 仮想メソッドが呼び出されると、その呼び出しが行われるインスタンスの ランタイム型 によって、呼び出す実際のメソッドの実装が決まります。

メソッドは、派生クラスでオーバーライド できます。 インスタンス メソッドの宣言に overridable 修飾子が含まれている場合、派生クラスによってメソッドをオーバーライドできます。 派生クラスがオーバーライド可能な基底クラス メソッドを実際にオーバーライドするかどうかは、実装によって決まります。メタデータには存在しません。 派生クラスが基底クラス内のメソッドを再宣言した場合、派生クラス メソッドと共に配置される新しいメソッドを、オーバーライドするのではなく宣言します。

インスタンス メソッドの宣言に protected 修飾子が含まれている場合、メソッドは派生クラスにのみ表示されます。

イベント

イベント 宣言は、クラスがイベント ソースであることを指定するメンバーです。 このようなイベント ソースは、デリゲート (特定のシグネチャを持つメソッド) を実装するすべての受信者に通知を提供します。

event キーワードを使用してイベントを宣言し、その後にデリゲート型名 (必要なメソッド シグネチャを記述) を続けて、イベントの名前を宣言します。 プラットフォームの既存のデリゲート型を使用するイベントの例を次に示します。

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

イベント宣言は、2 つのメソッドを暗黙的にクラスに追加します。add メソッド。クライアントが呼び出してソースにイベント ハンドラーを追加し、削除 メソッドを削除します。このメソッドは、クライアントが以前に追加したイベント ハンドラーを削除するために呼び出します。 その他の例を次に示します。

// 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;

慣例により、2 つのパラメーターが常に Windows ランタイム イベント ハンドラーに渡されます。送信者の ID とイベント引数オブジェクトです。 送信者は、イベントを発生させたオブジェクト、または静的イベントの場合は null です。 イベントに意味のあるペイロードがない場合、イベント引数は値が null である Object です。

デリゲート

デリゲート型 は、特定のパラメーター リストと戻り値の型を持つメソッドを指定します。 イベントの 1 つのインスタンスには、デリゲート型のインスタンスへの任意の数の参照を含めることができます。 宣言は、ランタイム クラスの外部に存在し、delegate キーワードのプレフィックスが付いている点を除き、通常のメンバー メソッドの宣言と似ています。

デリゲートを使用すると、メソッドを、変数に割り当て、パラメーターとして渡すことができるエンティティとして扱うことができます。 デリゲートは、他の言語で見つかる関数ポインターの概念に似ています。 ただし、関数ポインターとは異なり、デリゲートはオブジェクト指向で型セーフです。

プラットフォームからデリゲート型 WindowSizeChangedEventHandler を使用しない場合は、独自のデリゲート型を定義できます。

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

SizeChangedHandler デリゲート型のインスタンスは、2 つの引数 (オブジェクトWindowSizeChangedEventArgs) を受け取り、void を返す任意のメソッドを参照できます。 構造体説明したら、WindowSizeChangedEventArgs パラメーターを独自の型 イベント引数に置き換えることもできます。

デリゲートの興味深く便利なプロパティは、デリゲートが参照するメソッドのクラスを認識したり、気にしたりしないという点です。重要なのは、参照されるメソッドがデリゲートと同じパラメーターと戻り値の型を持つということです。

必要に応じて、[uuid(...)]を使用してデリゲート宣言を属性化できます。

HRESULTを返すデリゲート も参照してください。

構造体

構造体 は、データ メンバー (フィールド) を含むことができるデータ構造体です。 ただし、クラスとは異なり、構造体は値型です。

構造体は、値セマンティクスを持つ小さなデータ構造に特に便利です。 複素数(座標系内の点)は、構造体の良い例です。 小さなデータ構造に対してクラスではなく構造体を使用すると、アプリケーションが実行するメモリ割り当ての数に大きな違いが生じます。

例を使用して、クラスと構造体を比較してみましょう。 クラスとして最初に Point のバージョンを次に示します。

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

この C# プログラムは、Pointの 100 個のインスタンスの配列を作成して初期化します。 Point クラスとして実装されると、101 個の個別のオブジェクトがインスタンス化されます。配列オブジェクト自体用に 1 つ。100 Point 要素ごとに 1 つ。

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;
};

これで、1 つのオブジェクト (配列オブジェクト自体) のみがインスタンス化されます。 Point 要素は、配列内の行に格納されます。プロセッサ キャッシュが強力な効果を発揮するために使用できるメモリ配置。

構造体の変更は、バイナリ破壊的変更です。 そのため、Windows 自体の一部として実装された構造体は、導入後は変更されません。

インターフェイス

インターフェイス は、クラスによって実装できるコントラクトを定義します。 インターフェイスには、クラスと同様に、メソッド、プロパティ、およびイベントを含めることができます。

クラスとは異なり、インターフェイスは定義するメンバーの実装を提供しません。 インターフェイスを実装する任意のクラスによって提供される必要があるメンバーを指定するだけです。

インターフェイス 、他のインターフェイスも実装するために、インターフェイスを実装するクラス 必要になる場合があります。 次の例では、IComboBox インターフェイスでは、IComboBox実装するすべてのクラスが、ITextBox と IListBox両方を実装する必要があります。 さらに、IComboBox 実装するクラスは、IControl実装する必要もあります。 これは、ITextBox と IListBox の両方する必要があるためです。

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 クラスは、IControl と IDataBoundの両方を実装します。

interface IDataBound
{
    void Bind(Binder b);
}

runtimeclass EditBox : IControl, IDataBound
{
}

Windows プラットフォームの Windows ランタイム型の場合、これらの型を使用する開発者がインターフェイスを実装することが期待される場合は、インターフェイスが定義されます。 インターフェイスを定義するためのもう 1 つのユース ケースは、複数のランタイム クラスがインターフェイスを実装し、それらのランタイム クラスを使用する開発者が、その共通インターフェイスを介してさまざまな種類のオブジェクトに一般的に (したがってポリモーフィックに) アクセスする場合です。

手記

MIDL 3.0 で requires キーワードを使用する方法についてもう一度検討してください。 これは、特にバージョン管理が考慮されている場合に、乱雑な設計につながる可能性があります。

列挙型

列挙型 (または列挙型)は、名前付き定数のセットを持つ個別の値型です。 次の例では、Color という名前の列挙型を定義して使用します。RedGreenBlueの 3 つの定数値を使用します。

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

各列挙型には、列挙型の基になる型 と呼ばれる対応する整数型があります。 列挙型の基になる型は、Int32 するか、UInt32します。

Windows ランタイムでは、通常の 列挙型 と、列挙型 フラグ の 2 種類の列挙型がサポートされています。 通常の種類の列挙型は、一連の排他的な値を表します。フラグの種類の 1 つはブール値のセットを表します。 フラグ列挙型に対してビット演算子を有効にするには、MIDL 3.0 コンパイラによって C++ 演算子オーバーロードが生成されます。

フラグ列挙型には、[flags] 属性が適用されています。 その場合、列挙型の基になる型は UInt32です。 属性が存在しない場合 (通常の列挙型)、列挙型の基になる型は Int32されます。 列挙型を他の型として宣言することはできません。

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

列挙型のストレージ形式と使用可能な値の範囲は、基になる型によって決まります。 列挙型が受け取ることができる値のセットは、宣言された列挙型メンバーによって制限されません。

次の例では、Alignmentという名前の列挙型 Int32の基になる型を定義します。

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

C および C++ の場合も同様に、MIDL 3.0 列挙型には、メンバーの値を指定する定数式を含めることができます (上記参照)。 各列挙型メンバーの定数値は、列挙型の基になる型の範囲内にある必要があります。 列挙型メンバー宣言で値が明示的に指定されていない場合、メンバーには値 0 が与えられます (列挙型の最初のメンバーの場合)、またはテキストの前にある列挙型メンバーの値に 1 を加算します。

次の例では、Permissionsという名前の列挙型を定義し、基になる型 UInt32を指定します。

[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;
}

属性を適用するには、関連付けられた宣言の直前の角かっこ内に、任意の引数と共に名前を付けます。 属性の名前が Attribute で終わる場合は、属性を参照するときに名前のその部分を省略できます。 たとえば、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_alltarget_delegatetarget_enumtarget_eventtarget_fieldtarget_interfacetarget_methodtarget_parametertarget_propertytarget_runtimeclass、および target_structです。 かっこ内に複数のターゲットをコンマで区切って含めることができます。

属性に適用できるその他の属性は、[allowmultiple][attributename("<name>")]です。

パラメーター化された型

次の例では、エラー MIDL2025が生成されます。[msg]構文エラー [context]: > を想定しています。または、">>"に近い場合です。

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

代わりに、テンプレート終了文字のペアが右シフト演算子として誤って解釈されないように、2 つの > 文字の間にスペースを挿入します。

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

次の例では、エラー MIDL2025が生成されます:[msg]構文エラー [context]: > を想定しているか、"["付近です。 これは、パラメーター化されたインターフェイスのパラメーター型引数として配列を使用することは無効であるためです。

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

解決策については、「非同期的に配列を返す」を参照してください。