メタデータ API のコーディング規則

このトピックでは、メタデータ API で使用されるコーディング規則について説明します。

文字列パラメーターの処理

メタデータ API は、すべての文字列を Unicode 形式で公開します。 実際には、ディスク上のシンボル名形式は UTF-8 ですが、メタデータ API クライアントからは非表示です。 返されるすべての文字列は次の 3 つのパラメーターから成ります (実際のパラメーター名は異なります)。

  • [入力] ULONG cchString : 文字列 (終端の null 文字を含む) が返されるバッファーのバイト単位によるサイズ。

  • [出力] LPCWSTR wzString : 文字列が返されるバッファーへのポインター。

  • [出力] ULONG *pchString : 返される文字列 (終端の null 文字を含む) のサイズへのポインター。 バッファーが小さすぎてすべての文字列を格納できない場合、返される文字列は切り捨てられ、エラーが返されます。クライアントは必要に応じてバッファーを再割り当てし、再試行できます。

シンボル名

次の規則は、文字列パラメーターのシンボル名に適用されます。

  • シンボル名である文字列パラメーターは必ず null で終わることが前提となっており、長さの [入力] パラメーターは必要ありません。 埋め込み null 文字はサポートされません。

  • [入力] パラメーター文字列が長すぎて切り捨てなしでは保持できない場合、エラーが返されます。

ユーザー文字列

次の規則は、ユーザー指定文字列パラメーターに適用されます。

  • ユーザー文字列には、null 文字を埋め込むことができ、null 終端文字を含めることはできません。

  • 長さは、cchString パラメーターに指定する必要があります。 バッファーのサイズは、格納される文字列の正確な長さにする必要があります。

既定値の格納

フィールド、パラメーター、およびプロパティの既定値として、定数をメタデータに格納できます。 次の 3 つのパラメーターを使用して定数を指定します (実際のパラメーター名は異なることがあります)。

  • [入力] DWORD dwCPlusTypeFlag - 既定値の型を指定する CorElementType 列挙型の値。

  • [入力] void const *pValue : 実際の既定値へのポインター。 たとえば、0x0000002A を保持する 4 バイトの DWORD へのポインターは、メタデータ内に 42 桁の DWORD 値を格納します。 dwCPlusTypeFlag に指定される既定値の型は、プリミティブまたは文字列に限定されます。 dwCPlusTypeFlag が ELEMENT_TYPE_CLASS である場合、既定値は null になります。

  • [入力] ULONG cchValue : pValue がポイントする Unicode 文字数 (バイト シーケンス単位)。 これは、dwCPlusTypeFlag に指定されている型が ELEMENT_TYPE_STRING である場合のみ必須です。 他の場合はすべて、長さは型から推論されます。

既定値は、初期化コードと静的に初期化されたデータ領域のいずれにも自動挿入されません。 これらは、単純にメタデータ内に記録されます。

既定値を指定しない場合、dwCPlusTypeFlag のすべてのビットを設定します (値を -1 に設定します)。

戻り値を受け取るパラメーターの null ポインター

メタデータ API は最低限のエラー チェックを行うため、次の状況では戻り値を受け取るパラメーターに非 null ポインターを想定しています。

  • Define メソッドでは、返されたトークンに対して非 null ポインターが必要です。 これらのメソッドは、定義するアイテムを作成し、アイテムのトークンを返します。 必要ない場合はトークンを破棄することを選択できます。

  • Find メソッドは、アイテムのトークンが正常に見つかった場合は常にそのトークンを返します。

  • Get メソッドでは、戻す必要がないパラメーター内に null を渡すことができます。

  • Set メソッドには、通常は戻り値がありません。 トークン内に、更新する値と一緒に更新するアイテムを渡すと、メソッドが更新を実行します。

無視されるパラメーター値

メタデータ API のいくつかのメソッドでは、以前に定義したアイテムのプロパティを変更できます。 次の例では、IMetaDataEmit::SetFieldProps メソッドを使用してフィールドのプロパティを変更します。プロパティは事前に IMetaDataEmit::DefineField への呼び出しで指定されていました。

HRESULT SetFieldProps(mdFieldDef fd, DWORD dwFieldFlags,
        DWORD dwDefType, void const *pValue, ULONG cchValue)

dwFieldFlags と pValue の一方のみを変更し、一方を変更しない場合があります。 この場合、パラメーター値を変更しない場合でも、エラーを避けるためにパラメーター値を渡す必要があります。 ただし、その値を変更しない場合、特定の値を渡すことにより、その引数を無視するように指定できます。 メソッドの引数を無視する場合にメタデータ API は次の規則を使用します。

  • パラメーターがポインター型である場合、null ポインターを渡します。

  • パラメーターが値型である場合 (通常はフラグ ビットマスク)、すべてのビットを設定する値 (–1) を渡します。

返されるエラー

IMetaDataDispenserExIMetaDataEmit、および IMetaDataImport の各インターフェイスでは、ほとんどすべてのメソッドが結果を示す HRESULT 値を返します。 操作が成功した場合は、これは値 S_OK です。 呼び出しがエラーになった場合は、操作が失敗した理由を説明する別の値が返されます。

すべてのメタデータ API で一般的なパターンとしては、呼び出し元が結果よりも小さい文字列バッファーを指定すると、API はできるだけ多くの数の文字をコピーし、S_OK ではなく、CLDB_S_TRUNCATION の HRESULT 値を返します。

IMetadata インターフェイスの呼び出し元はコンパイラまたはツールです。 エラーを検出するために、呼び出し元が各呼び出しのリターン ステータスを常にチェックすることが重要です。 この場合、エラー条件はユーザー (アプリケーション プログラムなど) ではなく、直接の呼び出し元 (コンパイラなど) の問題を反映します。

メモリ管理

汎用 COM の既定では、呼び出し先が割り当てたメモリは呼び出し元が解放します。 ただし、メタデータ メソッドの動作は異なります。

多くのメタデータ メソッドは、メモリのブロックに対する [出力] ポインターを返します。 このようなメモリは、モジュールのメタデータ ヒープの一部であり、共通言語ランタイム (CLR: Common Language Runtime) によって所有されます。 したがって、CLR が所有するメタデータのメモリ内ストレージを直接示すポインターを受け取るので、アプリケーションでメモリを解放する必要はありません。

ジェネリックのサポート

.NET Framework Version 2.0 では、メタデータ API は大幅に拡張され、ジェネリック (別名 "パラメーター ポリモーフィズム") をサポートしています。 ジェネリックは C++ のテンプレートに似ています。 次の例は、C# でジェネリック クラスを定義しています。

public class Dictionary<Key, Val> { . . . }

この場合、Dictionary クラスは Key と Val という 2 つのジェネリック パラメーターを使用してパラメーター化されています。 このクラスをインスタンス化する場合、次の例のようにジェネリック パラメーターの型を選択します。

Dictionary<string, int> NameToPhone = new Dictionary<string, int>();
Dictionary<int, string> PhoneToName = new Dictionary<int, string>();

参照

概念

メタデータの概要