向 Windows 运行时组件传递数组

在 Windows 运行时中,参数用于输入或输出,但从不同时用于输入和输出。 这意味着,传递给方法的数组内容以及数组本身用于输入或输出。 如果数组的内容用于输入,则方法会从数组中读取,但不向其中写入内容。 如果数组的内容用于输出,则方法会向数组中写入内容,但不从其中读取内容。 这会给数组参数带来问题,因为 .NET framework 中的数组是引用类型,并且即使数组引用通过值(Visual Basic 中的 ByVal)传递,数组的内容也是可变的。 Windows 运行时元数据导出工具 (Winmdexp.exe) 要求通过将 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 运行时组件编写的单元测试。 如果用托管代码编写测试,则数组内容在测试期间将显示为可变。

请参见

参考

ReadOnlyArrayAttribute

WriteOnlyArrayAttribute

概念

用 C# 和 Visual Basic 创建 Windows 运行时组件