简体   繁体   中英

Why is C# null translated as Empty in VB6, instead of Nothing

I have a C# application that reference a VB6 dll. When I pass null from C# into VB6 dll function, the null is translated as value Empty (value) in VB6, instead of Nothing (object). For example:

 // 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);
 }

When I pass an object (not null) then it will be passed into the VB6 as object. But when null passed into vb6, it becomes value type Empty, instead of object type Nothing. Any one knows why? and is there anyway I can force null as Nothing in VB6 when passed from c# app?

Thanks a lot.

Some more information, rather than an answer. I just ran this VB6 scratch program to confirm whether Nothing can be passed ByVal . It can be.

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

I got the following output. Note that 9 is vbObject and indicates a Variant holding an Object reference.

 9 
 9 
vnt Is Nothing

I haven't tested moving TestStub into another component but I think that'd still work. So I think the .NET marshalling to COM could do better.

The reason is probably that it's a ByVal function. null is probably marshaled to a valuetype Variant that's as 'null' as possible.

Since you aren't supposed to modify the functions in the VB dll, what about adding one?

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

Presumably this would work as 1) it's a sub an not a function, so there's no return value and 2) you're passing by value so it's not modifying the object itself.

Have you tried:

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

 }

Edit - And I would agree wtih Sander Rijken's answer as to why Empty is being returned instead of null

I followed a suggestion from another website and used System.DBNull.Value in a COM method call. That worked for me where passing the C# null did not.

As the parameter for the VB6 method is a Variant you should be testing for Nothing, Missing and Empty because they are the possible "not value or object" that can be passed when no real value or object is available.

In answer to your question, i think it is because a Variant in VB6 defaults to Empty, if your parameter was of type Object Nothing will be passed in, in your case.

You may want to try passing Nothing from VB.Net and seeing what happens, if the Nothing persists to the VB6 DLL then you know it is possible to pass it in and will find the answer by looking at the IL code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM