Windows ランタイム コンポーネントへの配列の引き渡し
Windows ランタイム では、パラメーターは入力用または出力用のどちらかで、両方ではありません。 つまり、メソッドに渡される配列の内容および配列自体は、入力用または出力用になります。 配列の内容が入力用の場合、メソッドは配列から読み取りますが書き込みません。 配列の内容が出力用の場合、メソッドは配列に書き込みますが読み取りません。 これは配列パラメーターにとって問題となります。.NET Framework の配列は参照型であり、配列参照が値 (Visual Basic の ByVal) によって渡される場合でも、配列の内容が変更可能であるためです。 Windows ランタイム メタデータ エクスポート ツール (Winmdexp.exe) では、配列の用途がコンテキストから明確でない場合、パラメーターに ReadOnlyArrayAttribute 属性または WriteOnlyArrayAttribute 属性を適用して、用途を指定する必要があります。 配列の用途は次のように決定されます。
戻り値または out パラメーター (Visual Basic では OutAttribute 属性の ByRef パラメーター) の場合、配列は常に出力用となります。 ReadOnlyArrayAttribute 属性は適用しないでください。 WriteOnlyArrayAttribute 属性は出力パラメーターで許可されますが、重複することになります。
注意
Visual Basic コンパイラは出力のみの規則を強制しません。出力パラメーターから読み取ることは避けてください。Nothing が含まれる場合があります。必ず新しい配列を割り当てます。
ref 修飾子 (Visual Basic の ByRef) を持つパラメーターは許可されません。 Winmdexp.exe (Windows ランタイム メタデータのエクスポート ツール) がエラーを発生させます。
値によって渡されるパラメーターでは、配列の内容が入力用か出力用かを指定するために、ReadOnlyArrayAttribute 属性または WriteOnlyArrayAttribute 属性を適用する必要があります。 両方の属性を指定するとエラーになります。
メソッドが入力用の配列を受け入れる、配列の内容を変更する、および配列を呼び出し元に返す必要がある場合、入力用に読み取り専用のパラメーターを使用し、出力用に書き込み専用のパラメーター (または戻り値) を使用します。 このパターンを実装する方法を次のコードに示します。
public int[] ChangeArray([ReadOnlyArray()] int[] input)
{
int[] output = input.Clone();
// Manipulate the copy.
// ...
return output;
}
Public Function ChangeArray(<ReadOnlyArray> input() As Integer) As Integer()
Dim output() As Integer = input.Clone()
' Manipulate the copy.
' ...
Return output
End Function
入力配列のコピーをすぐに作成し、コピーで操作することをお勧めします。 これにより、コンポーネントが .NET Framework コードによって呼び出されるかどうかに関係なく、メソッドが同じ動作をすることを保証できます。
マネージ コードおよびアンマネージ コードからのコンポーネントを使用する
ReadOnlyArrayAttribute 属性または WriteOnlyArrayAttribute 属性を持つパラメーターは、呼び出し元がネイティブ コードまたはマネージ コードで記述されているかどうかに応じて動作が異なります。 呼び出し元がネイティブ コード (JavaScript または Visual C++ コンポーネント拡張) の場合、配列の内容は次のように扱われます。
ReadOnlyArrayAttribute: 配列は、呼び出しがアプリケーション バイナリ インターフェイス (ABI) の境界を越えるとコピーされます。 必要に応じて、要素は変換されます。 そのため、メソッドが入力専用配列に誤って変更を加えても、呼び出し元には表示されません。
WriteOnlyArrayAttribute: 呼び出されたメソッドは、元の配列の内容に関する想定を行うことはできません。 たとえば、メソッドが受け取る配列は初期化されていない場合や、既定値が含まれている場合もあります。 メソッドは、配列のすべての要素の値を設定することが期待されます。
呼び出し元がマネージ コードの場合、元の配列は、.NET Framework の任意のメソッド呼び出しにあるため、呼び出されたメソッドで使用できます。 配列の内容は .NET Framework コードで変更可能であるため、メソッドが配列に行う変更は呼び出し元に表示されます。 これは Windows ランタイム コンポーネント用に記述された単体テストに影響するため覚えておく必要があります。 テストがマネージ コードで記述されている場合、配列の内容はテスト中に変更できるように表示されます。