Why does constructor ORDER matter in VB.Net? I am building a .Net type library which is meant to wrap an underlying COM library completely so that the consumers of the API can pretend to use a nice .Net library with .Net collections and whatnot instead of a COM library.
Currently most of my classes are just 1 to 1 wrappers built using Reflection and CodeDOM. These classes have an internal constructor which takes the underlying COM type as a parameter. The CodeDOM builds this as the first constructor to the class. Using these classes from C# proves to be no problem. All I need is a reference to the .Net library and all works good.
The problems appear when I try using these classes from a VB.Net project. If the first constructor has a COM type as an argument, the VB.Net project requires the COM interop assembly as a reference. If the first constructor has no arguments or has only managed types all works good. My class library is written in C#.
The following works:
public class ObjectID
{
public ObjectID(int type, int id)
{
this.Type = type;
this.ID = id;
}
internal ObjectID(COMLib.ObjectID id) : this(id.Type, id.ID) { }
public int ID { get; set; }
public int Type { get; set; }
internal COMLib.ObjectID ToCOM()
{
COMLib.ObjectID id = new COMLib.ObjectID();
id.ID = this.ID;
id.Type = this.Type;
return id;
}
}
The following requires a reference to the COMLib.Interop assembly:
public class ObjectID
{
internal ObjectID(COMLib.ObjectID id) : this(id.Type, id.ID) { }
public ObjectID(int type, int id)
{
this.Type = type;
this.ID = id;
}
public int ID { get; set; }
public int Type { get; set; }
internal COMLib.ObjectID ToCOM()
{
COMLib.ObjectID id = new COMLib.ObjectID();
id.ID = this.ID;
id.Type = this.Type;
return id;
}
}
Now I can solve this by creating a dummy private constructor to these classes as the first constructor but I'm more curious about what causes this? Why does the order of the constructor declarations matter in VB.Net?
Update
This sounded so insane that I started doubting it myself. Managed to replicate it with 3 projects.
C# Class library: Wrapped
namespace Wrapped
{
public class Class1
{
}
}
C# Class library: Wrapper
namespace Wrapper
{
public class Class1
{
internal Class1(Wrapped.Class1 c) { }
public Class1() { }
}
}
VB.Net Console app: Referer
Module Module1
Sub Main()
Dim w As New Wrapper.Class1
End Sub
End Module
Wrapper refers to Wrapped Referer refers to Wrapper Referer does NOT refer to Wrapped
Dim w As New Wrapper.Class1
Produces an error
Reference required to assembly 'Wrapped, Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=null'
containing the type 'Wrapped.Class1'.
Add one to your project.
Swapping the order of constructors takes care of the error.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=442224
Update after playing around some more
Causes error: No error:
Vb-ReferTest Vb-RefererTest
| | Fixes error in Vb-
V V RefererTest even
Cs-Wrapper Cs-Wrapper Vb-Wrapper <- if the Vb-Wrapper
| \ / and the RefererTest
V V V have no direct
Cs-WrappedLibrary Cs-WrappedLibrary relationship
If correct (I can't easily verify), that is fasinating. The order shouldn't matter, AFAIK. If you are sure about it, then perhaps log as a bug on connect (with sample code).
Confirmed as a bug. Too difficult to fix for it to be worth it too, so I guess we'll just live with it. Fortunately it seems to require cross language projects with uncommon class setups to crop up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With