C#中KeyValuePair[]的VB等价类型及动态添加、跨语言封送问题
问题解答
1. 结构的官方名称
你所使用的结构是非泛型KeyValuePair结构体的数组。需要注意的是,这里的KeyValuePair并非.NET框架默认提供的泛型KeyValuePair<TKey, TValue>,而是用于与C++例程交互的特定非泛型结构体(包含key整数字段和value字符串字段)。后续检索时可以称其为「KeyValuePair结构数组」,若需区分泛型版本,可明确为「非泛型KeyValuePair数组」。
2. 动态添加元素的方法
由于VB中的数组是固定长度的,无法直接动态添加元素,推荐先使用集合类存储元素,再转换为目标数组:
- 声明一个
List(Of KeyValuePair)(注意是与C++交互的非泛型结构体,而非泛型版本) - 调用
Add方法动态添加元素 - 最后通过
ToArray()方法将集合转换为KeyValuePair()数组
示例代码:
Dim dataList As New List(Of KeyValuePair)() ' 动态添加元素 dataList.Add(New KeyValuePair() With {.key = 1234, .value = "Atlanta"}) dataList.Add(New KeyValuePair() With {.key = 70, .value = "Atlanta"}) ' 转换为数组 Dim dataArray As KeyValuePair() = dataList.ToArray()
解决泛型类型无法封送的错误
你遇到的Cannot marshal 'parameter #4': Generic types cannot be marshaled.错误,原因是.NET泛型类型(如List(Of KeyValuePair(Of Integer, String)))无法直接封送到非托管C++代码。解决步骤如下:
步骤1:定义匹配的非泛型结构体
确保VB中使用的KeyValuePair结构体与C++例程中的结构完全匹配,可手动定义:
<StructLayout(LayoutKind.Sequential)> Public Structure KeyValuePair Public key As Integer Public value As String End Structure
步骤2:修改构建函数使用非泛型集合
将泛型集合替换为非泛型List(Of KeyValuePair),构建完成后转换为数组返回:
Private Function buildDataRecord(ByRef objRecord As OracleDataReader) As KeyValuePair() Dim lstFieldData As New List(Of KeyValuePair)() Dim strFieldName As String On Error GoTo buildDataRecordError For i As Integer = 0 To objRecord.FieldCount - 1 strFieldName = objRecord.GetName(i) If strFieldName.StartsWith("IN_") Then Dim kvp As New KeyValuePair() kvp.key = CInt(strFieldName.Substring(3)) kvp.value = Trim(objRecord(i).ToString()) lstFieldData.Add(kvp) End If Next ' 转换为数组返回 Return lstFieldData.ToArray() buildDataRecordError: Err.Raise(Err.Number, "buildDataRecord", Err.Description, Err.HelpFile, Err.HelpContext) End Function
步骤3:调用C++例程时使用数组参数
直接将返回的KeyValuePair()数组作为参数传递给C++例程,此时封送器可正确处理非泛型结构体数组。
内容的提问来源于stack exchange,提问作者Paul Stearns
相关产品推荐
相关产品推荐

