Почему это, на первый взгляд, правильный код .NET не скомпилируется? - PullRequest
29 голосов
/ 25 октября 2011

Я спрашиваю, если мне не хватает чего-то очевидного, но, возможно, я наткнулся на ошибку в компиляторе .NET.

У меня есть два проекта в решении .NET, один Visual Basicодин код C #.

C #, состоящий из трех перегруженных статических методов со значениями по умолчанию:

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 код, вызывающий один из перегруженных методов:

Option Explicit On
Option Strict On
Imports ClassLibrary1

Module Module1
    Sub Main()
        Dim x As Integer
        Class1.TestFunc(x, 0)
    End Sub
End Module

Скомпилировать этот код не удастся, сказав:

'TestFunc' является неоднозначным, поскольку в классе 'ClassLibrary1.Class1' существует несколько видов членов с этим именем.

Почему он считает этот метод неоднозначным?Существует только один Class1.TestFunc с (int, int) подписью.Это ошибка, или я что-то упустил?

Ответы [ 5 ]

23 голосов
/ 25 октября 2011

В конечном итоге все сводится к тому, как C # реализует необязательные параметры в вашем первом статическом методе. Если вы удалите значение по умолчанию для этого, ваше решение должно скомпилироваться.

public static void TestFunc(int val1, int val2) 
{ 
} 

На самом деле, в этом случае я несколько удивлен, что C # компилируется. Вы должны использовать необязательные параметры в C # или перегрузки, но не оба. Например, как бы вы недвусмысленно сказали следующее:

public static void TestFunc(int val1, int val2 = 0)     
{     
}     

public static void TestFunc(int val1)     
{     
}  

Если я укажу следующее, какой из двух методов должен быть выполнен - ​​один с необязательным параметром или второй без второго параметра?

TestFunc(1)

Лучшее решение, если вы хотите включить необязательные параметры в реализацию C #, - объединить первый и второй методы и при необходимости проверить значение по умолчанию:

public static void TestFunc(int val1, int val2 = 0)
{
}

public static void TestFunc(string val1, int val2 = 0)
{
}

Обратите внимание, что с помощью этой версии VB IS может определить, какой метод вызывать.

15 голосов
/ 25 октября 2011

Если вы попытаетесь скомпилировать это в VB.NET, вы получите

Sub TestFunc(ByVal val1 As Integer, Optional ByVal val2 As Integer = 0)

End Sub

Sub TestFunc(Optional ByVal val1 As Integer = 0)

End Sub

, вы получите 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.

, поэтому я скажу, что VB.NET болееограничено C # в необязательных параметрах перегрузки.

2 голосов
/ 25 октября 2011

В спецификации языка Visual Basic 10 указано, что.

Считается, что метод с необязательными параметрами имеет несколько подписи, по одной для каждого набора параметров, которые могут быть переданы звонящий. Например, следующий метод имеет три соответствующих Подписи:

 Sub F(x As Short, _
       Optional y As Integer = 10, _
       Optional z As Long = 20)

Итак, ваш TestFunc(int val1, int val2 = 0) имеет две подписи в VB, что противоречит TestFunc(int val1), поэтому TestFunc неоднозначно.

Я не могу найти ничего в спецификации C #, в которой говорится, что необязательные параметры рассматриваются как методы с несколькими сигнатурами. Из поведения, которое вы видите, я предполагаю, что в C # они не считаются множественными сигнатурами, в противном случае вы получите ошибку компилятора - это означает, что она допустима в C #. Я предполагаю, что C # выберет метод, который вызывается на основе некоторых правил, поскольку он не может вызвать оба для TestFunc(0).

2 голосов
/ 25 октября 2011

TestFunc неоднозначен из-за параметра по умолчанию.Когда вызывается TestFunc (x), он не уверен, вызывает ли он TestFunc с одним параметром или TestFunc с параметрами 2 по умолчанию. 2-й параметр является значением по умолчанию.

2 голосов
/ 25 октября 2011

Редактировать

Когда этот вопрос был впервые опубликован, оба:

Option Strict On

и

Option Explicit On

былине ставится под вопрос, поэтому это резко меняет ответ.

Оригинальный ответ перед редактированием вопроса

Потому что это:

 public static void TestFunc(int val1, int val2 = 0) 
    { 
    } 

Неоднозначно:

public static void TestFunc(string val1, int val2 = 0) 
    {  
    } 

VB.net может преобразовать целое число в строку.

...