傳遞陣列給 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 程式碼是否呼叫您的元件,方法的運作方式都相同。
從 Managed 程式碼與 Unmanaged 程式碼使用元件
具有 ReadOnlyArrayAttribute 屬性或 WriteOnlyArrayAttribute 屬性的參數,會因為呼叫端是以機器碼或 Managed 程式碼撰寫的,而有不同的運作方式。 如果呼叫端是機器碼 (JavaScript 或 Visual C++ 元件擴充功能),則會將陣列內容視為:
ReadOnlyArrayAttribute:在呼叫跨越應用程式二進位介面 (ABI) 界限時,將會複製陣列。 視需要轉換項目。 因此,方法無意間對僅限輸入的陣列所做的任何變更,呼叫端都看不見。
WriteOnlyArrayAttribute:呼叫的方法無法對原始陣列的內容做任何假設。 例如,方法所接收的陣列可能未初始化,或可能包含預設值。 方法依預期應設定陣列中所有項目的值。
如果呼叫端是 Managed 程式碼,則呼叫的方法將可使用原始陣列,因為 .NET Framework 中的任何方法呼叫都會包含此陣列。 陣列內容在 .NET Framework 程式碼中是可變的,因此,呼叫端將可看見方法對陣列所做的任何變更。 請務必記住這一點,因為這會影響到為 Windows 執行階段元件撰寫的單元測試。 如果測試是以 Managed 程式碼撰寫的,陣列的內容在測試期間就可能是可變動。