6
votes

I am replicating a situation that I am facing.

Let's say we have an assembly, with C# class as:

public class Program
{
    int n = 0;

    public void Print()
    {
        Console.WriteLine(n);
    }

    public Program()
    {
    }

    public Program(int num = 10)
    {
        n = num;
    }
}

We refer the above assembly in VB.NET project and trying to create an instance of the Program class:

Module Module1 
    Sub Main()
        Dim p As New Program()
        p.Print()
        p = New Program(20)
        p.Print()
        Console.ReadLine()
    End Sub
End Module

The VB.NET project is not compiling, giving error:

'.ctor' is ambiguous because multiple kinds of members with this name exist in class 'ConsoleApplication2.Program'.

From the error message we can see the the VB.NET compiler is not sure which constructor to call - as one constructor is parameterless and other with one optional parameter. This issue is occurring in VS2010/.NET 4 and not in VS2012/.NET 4.5. Also in C# it is not givng any issues, it successfully compiles and runs the code of object initiaization of Program class.

Is there a way we can create Program class' instance in VB.NET + VS2010/.NET 4 without changing the constructors ?

2
Why do you want this construct? Is there a way that I'm missing that you can actually invoke the second constructor and have the compiler use the default parameter?Damien_The_Unbeliever
This code smells. It is ambitious without VB. What do you think num value should be for a use like var program = new Program()? Did you optionally want num to be 10 or is it default constructor where num is field initialized to be 0???Sinatr
@Sinatr, this is a replication of a situation that I am facing. I wrote it that way so that I can differentiate the output and identify which constructor was getting called in C#.Brij
It sounds like the VB compiler is doing you a favour to me.Jodrell
@Jodrell, fully agree, we should have it in C# as well :)Brij

2 Answers

8
votes

The problem is with the definitions of your constructors in the Program class

Because the argument to the second is optional, then both are candidates when calling using New Program(). This creates the ambiguity.

Instead, define your constructors using this sort of pattern:

public Program()
    : this(10)
{
}

public Program(int num)
{
    n = num;
}

or just the single constructor:

public Program(int num = 10)
{
    n = num;
}

(Personally I prefer the first of these).

0
votes

The best way would be to change the implementation of the constructor as also @JonEgerton wrote. If this is not possible, you could try the following - not really beautiful - workarounds:

  • If you know the inner implementation of the Program class, you can simply call the constructor with the int-Parameter with the value that the parameterless constructor assigns, in your sample Dim p As New Program(0). This implies that you need to be careful regarding later changes in the implementation of the constructors of the Program class as they will not be reflected in your implementation. For instance, if the implementors of the Program class change the value that is assigned in the parameterless constructor, your solution will still assign a value of 0.
  • As C# seems to handle the creation differently, you can also add a C# class (e.g. in a C# class library) that creates the instance of program for you and returns it to your code. Though this maybe means to add a class library to your solution for this sole purpose and therefore is not really a beautiful approach, later changes in the implementation of the Program class will be reflected in your program also.