高度なトピック、および短縮形
短縮形
名前空間を指定せずにパラメーター化された型を使用した場合、MIDL 3.0 コンパイラは Windows でそれを検索します。Foundation. Collections 名前空間。 実際には、次の短縮形を使用できます。
短いバージョン | 長いバージョン |
---|---|
IIterable<T> | Windows。IIterable < T> |
IIterator < T> | Windows。Foundation. コレクション. IIterator < T> |
IKeyValuePair<K, V> | Windows。Ikeyvaluepair |
IMap<K, V> | Windows。Foundation. IMap < K, V> |
」 < K> | Windows。」 < K> |
IMapView<K, V> | Windows。IMapView < K, V> |
IObservableMap < K、V> | Windows。IObservableMap < K, V> |
IObservableVector < T> | Windows。IObservableVector < T> |
IVector<T> | Windows。Foundation. IVector < T> |
IVectorView<T> | Windows。IVectorView < T> |
MapChangedEventHandler < K、V> | Windows。Foundation. MapChangedEventHandler < K、V> |
VectorChangedEventHandler < T> | Windows.Foundation.Collections.VectorChangedEventHandler<T> |
このメカニズムは、Windows には適用されません。Foundation名前空間。 たとえば、Windows の完全な名前を書き込む必要があります。Foundation. IAsyncAction。
オーバーロード
オーバーロードされたメソッドとコンストラクターの既定の動作では、インターフェイス内の2番目とそれ以降のオーバーロードの ABI 名に数値サフィックスを追加します。
[contract(Windows.Foundation.UniversalApiContract, 1)]
runtimeclass Sample
{
// ABI name is "DoSomething"
void DoSomething();
// ABI name is "DoSomething2"
void DoSomething(Int32 intensity);
[contract(Windows.Foundation.UniversalApiContract, 2)]
{
// ABI name is "DoSomething" (new interface)
void DoSomething(Int32 intensity, String label);
}
}
この既定の名前付けは、推奨される API デザインガイドラインと一致しないので、[method_name] 属性でオーバーライドします。
[contract(Windows.Foundation.UniversalApiContract, 1)]
runtimeclass Sample
{
void DoSomething();
[method_name("DoSomethingWithIntensity")]
void DoSomething(Int32 intensity);
[contract(Windows.Foundation.UniversalApiContract, 2)]
{
[method_name("DoSomethingWithIntensityAndLabel")]
void DoSomething(Int32 intensity, String label);
}
}
非 exclusiveto インターフェイスを実装する
インターフェイスからランタイムクラスを派生させると、そのインターフェイスのメンバーが自動的に宣言されます。 再宣言しないでください。 この場合、MIDL 3.0 コンパイラは、インターフェイスから隠ぺいされた別のメソッド M () を実装することを前提としています。
interface I
{
void M();
}
runtimeclass C : I
{
// Don't redeclare M(). It's automatically inherited from interface I.
// void M();
}
既定のインターフェイスを指定する
既定のインターフェイスを指定しない場合、MIDL 3.0 コンパイラは最初のインスタンスインターフェイスを選択します。 この選択をオーバーライドするには、インターフェイスの前に既定のインターフェイスとして使用する属性 [default]
を挿入します。
// Declaring an external interface as the default
runtimeclass C : [default]I { ... }
// Declaring a specific exclusiveto interface as the default.
// This is very unusual.
runtimeclass C
{
...
[default][interface_name(...)]
{
...
}
}
旧バージョンとの互換性の属性
MIDL 1.0 または MIDL 2.0 を MIDL 3.0 に変換する場合は (「 classic MIDLRT から midl 3.0 への移行」も参照)、通常は自動生成された値が既存の値と一致するようにカスタマイズする必要があります。
- インターフェイスの名前と UUID を指定するには、属性を使用
[interface_name("fully.qualified.name", UUID)]
します。 - ファクトリインターフェイスの名前と UUID を指定するには、属性を使用
[constructor_name("fully.qualified.name", UUID)]
します。 - 静的インターフェイスの名前と UUID を指定するには、属性を使用
[static_name("fully.qualified.name", UUID)]
します。 - 出力パラメーターの名前を指定するには、属性を使用
[return_name("name")]
します。 - メソッドの名前を指定するには、属性を使用
[method_name("name")]
します。
、 constructor_name
、および static_name
属性の interface_name
"UUID" 部分は省略可能です。 省略した場合、MIDL によって自動的に IID が生成されます。
[contract(Windows.Foundation.UniversalApiContract, 1)]
[interface_name("ISample", ceb27355-f772-407c-9540-6467a7199bc7)]
[constructor_name("ISampleFactory", 863B201F-BC7B-471E-A066-6425E8E639EC)]
[static_name("ISampleStatics", 07254c86-3b01-4e24-b52b-14e832c15483)]
runtimeclass Sample
{
[method_name("CreateWithIntensity")]
Sample(Int32 intensity);
static Boolean ShowConfigurationUI();
[return_name("count")]
Int32 GetCount();
[constructor_name("ISampleFactory2", FEA29CEC-7768-41DE-9A46-CAAAA4622588)]
[static_name("ISampleStatics2", 191235b5-a7b5-456f-86ea-abd1a735c6ab)]
[interface_name("ISample2", d870ed2e-915a-48a2-ad17-c05efa123db7)]
[contract(Windows.Foundation.UniversalApiContract, 2)]
{
[method_name("CreateWithIntensityAndLabel")]
Sample(Int32 intensity, String label);
static Boolean IsSupported();
[return_name("success")]
Boolean TrySomething();
}
}
注釈が混同された場合 xxx_name
、MIDL 3.0 コンパイラは警告を表示しません。 たとえば、次の例では、インターフェイスに interface_name
配置するインスタンスメンバーが存在しない場合でも、エラーなしでコンパイルされます。 属性が存在 interface_name
すると、 ISampleFactory2 という名前の空のインターフェイスが生成されます。
[contract(Windows.Foundation.UniversalApiContract, 1)]
[interface_name("ISample", ceb27355-f772-407c-9540-6467a7199bc7)]
runtimeclass Sample
{
[return_name("count")]
Int32 GetCount();
// !WRONG! Should be constructor_name.
[interface_name("ISampleFactory2", FEA29CEC-7768-41DE-9A46-CAAAA4622588)]
[contract(Windows.Foundation.UniversalApiContract, 2)]
{
// MIDL will autogenerate ISampleFactory since there is no [constructor_name]
Sample(Int32 intensity);
}
}
空のクラス
この使用法は少し不明瞭ですが、空のクラス (メンバーを持たないクラス)、または空のファクトリクラスを作成することが必要になる場合があります。 このような一般的な例として、 EventArgs クラスがあります。 イベントが発生した場合、イベントに対する引数は必要ありません (シグナル状態になっているイベントは追加のコンテキストを必要としません)。 API 設計ガイドラインでは、 EventArgs クラスを提供することを強くお勧めします。これにより、クラスは将来、新しいイベント引数を追加できるようになります。 ただし、この空のクラスを考えてみましょう。
runtimeclass MyEventsEventArgs
{
}
このエラーは、このクラスによって生成されます。
error MIDL5056 : [msg]a runtime class without a default attribute cannot be used as a parameter. Runtime classes must have methods or be flagged as marker classes if they are used as a parameter [context]: Windows.Widgets.MyEventsEventArgs [ RuntimeClass 'Windows.Widgets.MyEventsEventArgs' ( Parameter 'result' ) ]
この問題を解決するには、いくつかの方法があります。 最も簡単な方法は、属性を使用 [default_interface]
して、メソッドの欠如が意図的なものであり、作成エラーではないことを表すことです。 その実行方法を次に示します。
// An empty runtime class needs a [default_interface] tag to indicate that the
// emptiness is intentional.
[default_interface]
runtimeclass MyEventsEventArgs
{
}
もう1つの解決方法は、 [interface_name]
属性を使用することです。 通常のメソッドを持たないクラス (または、通常のメソッドを使用しないバージョン付きブロック) で MIDL がを検出 [interface_name]
すると、そのブロックに対して空のインターフェイスが生成されます。 同様に、または [constructor_name]
属性が、静的 (またはコンストラクター) のないクラスまたはバージョン付きブロックに存在する場合 [static_name]
、その静的インターフェイスまたはコンストラクターに対して空のインターフェイスが生成されます。
空のクラスと静的クラスを混同しないように注意してください。 空のクラスのインスタンスを持つことはできますが (ただし、何も実行しません)、静的クラスのインスタンスを持つことはできません。
空のインターフェイス
空のインターフェイス (マーカーインターフェイスとも呼ばれます) では、明示的 [uuid(...)]
なを指定する必要があります。
// An empty interface must specify an explicit [uuid] to ensure uniqueness.
[uuid("94569FA9-D3BB-4D01-BF7C-B8E1D8F8B30C")]
[contract(Windows.Foundation.UniversalApiContract, 1)]
interface ISomethingMarker
{
}
忘れた場合は、このエラーが生成されます。
error MIDL4010 : [msg]Cannot find the guid attribute of an interface or a delegate. [context]Windows.Widgets.ISomethingMarker
自動生成された Uuid はインターフェイスの内容のハッシュですが、空のインターフェイスに対して行われた場合、すべてのマーカーインターフェイスは同じ UUID で終了します。
スコープ列挙型
コマンドスイッチを MIDL 3.0 コンパイラに渡す /enum_class
と、コンパイラによって出力された列挙型がスコープ付き列挙型 (列挙クラス) として宣言されます。 パブリック型にはスコープ付き enum を使用しないでください。
コンポジションとアクティブ化
コンポーザブルなクラスの詳細については、「 XAML コントロール」を参照してください。
を指定 unsealed runtimeclass
すると、コンポーザブルなクラスを作成できます。 さらに、クラスが COM 集計を使用するか、標準のアクティブ化を使用するかを指定 unsealed runtimeclass unsealed
することもできます。 これは、パブリックコンストラクターを持つ基底クラスにとって重要です。
エラーメッセージの解釈
error MIDL2025: [msg]syntax error [context]: expecting > or, near ">>"
を >>
記述 IAsyncOperation<IVectorView<Something>>
した場合、は右シフト演算子として解釈されます。 この問題を回避するには、指定 IAsyncOperation<IVectorView<Something> >
する2つ以上の記号の間にスペースを入れます。
error MIDL2025: [msg]syntax error [context]: expecting . near ","
このエラーは、存在しないコントラクトを指定した場合に発生します。これは、場合によっては、ミスの可能性があります。
[contract(Windows.Foundation.UniversalApiContact, 5)]
^^^^^^^ typo
error MIDL5082: [msg]the version qualifying an enum's field cannot be less than the version of the enum itself
このエラーメッセージは、エラーメッセージの理由だけでなく、列挙型のフィールドを別のコントラクトに配置しようとした場合にも生成されます。 列挙型のフィールドは、同じコントラクトの異なるバージョンに属している必要がありますが、異なるコントラクトに完全に属することはできません。
error MIDL5161: [msg]Invalid method parameter name [context]: Parameter 'result' (or 'operation' or 'value')
パラメーター名 result
とはメソッドで予約されて operation
います。 パラメーター名 value
はコンストラクターで予約されています。
error MIDL5023: [msg]the arguments to the parameterized interface are not valid
インターフェイス名のスペルが正しいことを確認してください。
1つのインターフェイス内に MIDL 2.0 と MIDL 3.0 を混在させないでください
各インターフェイスとランタイムクラスは、完全な MIDL 2.0 であるか、完全な MIDL 3.0 である必要があります。 Midl 2.0 runtime クラスから MIDL 3.0 インターフェイスを参照すること は有効です 。
MIDL 2.0 と MIDL 3.0 を混在させようとすると、コンパイラはエンティティ全体を MIDL 2.0 として扱います。これにより、コンパイラエラーが発生します。 MIDL 3.0 を使用する場合に、誤って MIDL 2.0 構文を使用すると、この問題が発生する可能性があります。
interface ICollapsible
{
void Collapse();
boolean IsCollapsed { get; } // WRONG!
// ^^^^^^^ Lowercase "boolean" is MIDL 2.0.
Boolean IsCollapsed { get; } // RIGHT!
// ^^^^^^^ Uppercase "Boolean" is MIDL 3.0.
};
HRESULTを返すデリゲート
HRESULTを返すデリゲートがあいまいです。 これは、void ( HRESULT が例外の伝達に使用される) を公称で返すデリゲートの従来の (MIDL 3.0 より前の) 宣言か、 HRESULT を標準で返すデリゲートの最新の (MIDL 3.0) 宣言である可能性があります。
コンパイラは、宣言の他の部分を見て、あいまい性を解決します。 たとえば、パラメーターがクラシック構文で宣言されている場合、宣言はクラシックと見なされます。 パラメーターが最新の構文で宣言されている場合、宣言は最新であると見なされます。
delegate HRESULT AmbiguousDelegate(INT32 value, RuntimeClassName* r);
- パラメーターはクラシック構文を使用します。そのため、これはクラシック宣言と見なされます。
- 最新の同等の は です
delegate void AmbiguousDelegate(Int32 value, RuntimeClassName r);
。
delegate HRESULT AmbiguousDelegate(Int32 value, RuntimeClassName r);
- パラメーターは最新の構文を使用します。そのため、これは最新の宣言であると見なされます。
- 従来の同等の は です
delegate HRESULT AmbiguousDelegate(Int32 value, RuntimeClassName* r, [out, retval] HRESULT* result);
。
パラメーター リストがあいまいを解決するには不十分な場合があります。 たとえば、空のパラメーター リストや、列挙型だけで構成されるパラメーター リストは、クラシック構文と最新構文の両方で使用できます。 このような場合、MIDL 3.0 コンパイラは既定でクラシックに設定されます。
delegate HRESULT AmbiguousDelegate(MyEnum e);
- 従来のデリゲートとして解釈されます。デリゲートは通常 void を返し、HRESULT は例外を伝達します。
- HRESULT を返すデリゲートが本当に必要な場合は、クラシック構文 を使用する必要があります
delegate HRESULT AmbiguousDelegate(MyEnum e, [out, retval] HRESULT* result);
。
さいわい、HRESULT を公称で返すデリゲートを持 つケースはまれです。
JavaScript と Visual Basic の出力パラメーター
出力パラメーター の背景 情報については、「パラメーター」を参照してください。
JavaScript は、ほとんどの言語とは異なる方法 out
でパラメーターを持つメソッドをプロジェクト化します。 メソッドの戻り値の型が void out
out
で、パラメーターが 1 つの場合、パラメーターは メソッドによって返されます。 それ以外の場合、メソッドは 1 つの オブジェクトを返します。そのオブジェクトには、各パラメーターのプロパティと out
戻り値の別のプロパティがあります (void ではない場合)。 次の例では、メソッド呼び出しによって返される JavaScript オブジェクトに result という名前のプロパティと 、remainder という名前の別のプロパティ があります。
runtimeclass Test
{
static void Divide(Int32 x, Int32 y, out Int32 result, out Int32 remainder);
}
Visual Basic - only パラメーターはout
サポートされていません。 パラメーターを持つout
メソッドは、 Visual Basicとして処理されますByRef
。