Reputation: 17417
I'm asking in case I'm missing something obvious, but I think I may have stumbled upon a bug in .NET's compiler.
I have two projects in a .NET solution, one visual basic, one C#.
C# code, consisting of three overloaded static methods with default values:
public static class Class1
{
public static void TestFunc(int val1, int val2 = 0)
{
}
public static void TestFunc(int val1 = 0)
{
}
public static void TestFunc(string val1, int val2 = 0)
{
}
}
Visual basic code, calling one of the overloaded methods:
Option Explicit On
Option Strict On
Imports ClassLibrary1
Module Module1
Sub Main()
Dim x As Integer
Class1.TestFunc(x, 0)
End Sub
End Module
Compiling this code will fail, saying:
'TestFunc' is ambiguous because multiple kinds of members with this name exist in class 'ClassLibrary1.Class1'.
Why would it see this method as ambiguous? There is only one Class1.TestFunc with an (int, int) signature. Is this a bug, or am I missing something?
Upvotes: 29
Views: 2165
Reputation: 19842
In the Visual Basic Language Specification 10 it states that.
A method with optional parameters is considered to have multiple signatures, one for each set of parameters that can be passed in by the caller. For example, the following method has three corresponding signatures:
Sub F(x As Short, _
Optional y As Integer = 10, _
Optional z As Long = 20)
So your TestFunc(int val1, int val2 = 0)
has two signatures in VB, which clashes with TestFunc(int val1)
so TestFunc
is ambiguous.
I can't find anything in the C# specification which says that optional parameters are treated as methods with multiple signatures. From the behaviour you are seeing I assume that in C# they are not considered to have multiple signatures, otherwise you would get a compiler error - which means that it is valid in C#. I assume C# will choose the method that gets called based on some rules as it can't call both for TestFunc(0)
.
Upvotes: 2
Reputation: 111940
If you try to compile this in VB.NET you'll get
Sub TestFunc(ByVal val1 As Integer, Optional ByVal val2 As Integer = 0)
End Sub
Sub TestFunc(Optional ByVal val1 As Integer = 0)
End Sub
you'll get Public Sub TestFunc(val1 As Integer, [val2 As Integer = 0])' and 'Public Sub TestFunc([val1 As Integer = 0])' cannot overload each other because they differ only by optional parameters.
so I'll say that VB.NET is more limited than C# in optional parameters overload.
Upvotes: 15
Reputation: 10418
Ultimately it appears to come down to how C# is implementing the optional parameters in your first static method. If you remove the default value on that, your solution should compile.
public static void TestFunc(int val1, int val2)
{
}
Actually, in this case, I'm somewhat surprised that the C# compiles. You should either use optional parameters in C# or overloads, but not both. For example, how would you disambiguate the following:
public static void TestFunc(int val1, int val2 = 0)
{
}
public static void TestFunc(int val1)
{
}
If I pass in the following, which of the two methods should be executed - the one with the optional parameter or the second without the second parameter?
TestFunc(1)
A better solution if you want to include optional parameters in your C# implementation would be to combine the first and second methods and check your default value as necessary:
public static void TestFunc(int val1, int val2 = 0)
{
}
public static void TestFunc(string val1, int val2 = 0)
{
}
Note, using this version, VB IS able to disambiguate which method to call.
Upvotes: 23
Reputation: 33183
When this question was first posted both:
Option Strict On
and
Option Explicit On
were not put into the question so this changes the answer dramitically.
Because this:
public static void TestFunc(int val1, int val2 = 0)
{
}
Is ambiguious to:
public static void TestFunc(string val1, int val2 = 0)
{
}
VB.net can convert an integer to a string.
Upvotes: 2
Reputation: 1802
TestFunc is ambiguous because of default parameter. When TestFunc(x) is called, it is not sure if it is calling TestFunc with single parameter or TestFunc with default 2 parameters 2nd parameter being default one.
Upvotes: 2