为什么在VB6中C#null被翻译为空,而不是Nothing

时间:2010-01-13 17:59:54

标签: c# com vb6 com-interop

我有一个引用VB6 dll的C#应用​​程序。当我将C#中的null传递给VB6 dll函数时,null在VB6中被转换为值Empty(value),而不是Nothing(object)。例如:

 // function in vb6 dll that referenced by c# app
 Public Sub TestFunc(ByVal oValue As Variant)
 {
   ...
   if oValue is Nothing then
     set oValue = someObject
   end if
   ...

 }

 // main c# code
 private void Form1_Load(object sender, EventArgs e)
 {
    object testObject = new object();
    testObject = null;
    TestFunc(testObject);
 }

当我传递一个对象(非null)时,它将作为对象传递给VB6。但是当null传递给vb6时,它变为值类型为Empty,而不是对象类型Nothing。谁知道为什么?无论如何,当从c#app传递时,我可以强制null为VB6中的Nothing吗?

非常感谢。

6 个答案:

答案 0 :(得分:5)

更多信息,而不是答案。我刚刚运行了这个VB6临时程序来确认Nothing是否可以通过ByVal。有可能。

Private Sub Form_Load()
  Call TestSub(Nothing)
End Sub
Private Sub TestSub(ByVal vnt As Variant)
  Debug.Print VarType(Nothing)
  Debug.Print VarType(vnt)
  If vnt Is Nothing Then Debug.Print "vnt Is Nothing"
  If IsEmpty(vnt) Then Debug.Print "vnt Is Empty"
End Sub

我得到了以下输出。请注意,9是vbObject,表示持有Object引用的Variant。

 9 
 9 
vnt Is Nothing

我还没有测试过移动TestStub到另一个组件,但我认为它仍然有用。所以我认为.NET的COM编组可以做得更好。

答案 1 :(得分:3)

原因可能是它是ByVal函数。 null可能被编组为一个尽可能为'null'的值类型Variant。

答案 2 :(得分:3)

既然你不应该修改VB dll中的函数,那么添加一个呢?

Public Sub TestFuncEx(ByVal oValue As Variant)
{
   If IsEmpty(oValue) Then
    TestFunc(Nothing)
   Else
    TestFunc(oValue)
   End If
}

据推测,这可能会起作用1)它是一个子函数而不是一个函数,因此没有返回值,2)你正在传递值,所以它不会修改对象本身。

答案 3 :(得分:2)

你试过了吗?

Public Sub TestFunc(ByVal oValue As Variant)
 {
   ...
   If oValue Is Nothing Then
     Set oValue = someObject
   ElseIf IsEmpty(oValue) Then
     Set oValue = someObject
   End If
   ...

 }

编辑 - 我同意Sander Rijkens的回答,为什么Empty被归还而不是null

答案 4 :(得分:1)

我遵循了另一个网站的建议,并在COM方法调用中使用了System.DBNull.Value。这对我来说很有用,因为传递C#null没有。

答案 5 :(得分:0)

由于VB6方法的参数是Variant,您应该测试Nothing,Missing和Empty,因为它们是可能在没有实际值或对象可用时传递的“非值或对象”。

在回答您的问题时,我认为这是因为VB6中的Variant默认为Empty,如果您的参数类型为Object,则在您的情况下将传入Nothing。

您可能想尝试从VB.Net传递Nothing,看看会发生什么,如果Nothing持续存在于VB6 DLL,那么您知道可以传入它并通过查看IL代码找到答案。< / p>