w.brian
w.brian

Reputation: 17417

Why won't this seemingly correct .NET code compile?

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

Answers (5)

Chris Diver
Chris Diver

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

xanatos
xanatos

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

Jim Wooley
Jim Wooley

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

JonH
JonH

Reputation: 33183

Edit

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.

Original answer before question edit

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

Birey
Birey

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

Related Questions