Подтвердить что ты не робот

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

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

У меня есть два проекта в .NET-решении, один визуальный базовый, один С#.

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

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)
    { 
    }
}

Визуальный базовый код, вызывающий один из перегруженных методов:

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). Это ошибка, или я чего-то не хватает?

4b9b3361

Ответ 1

Если вы попытаетесь скомпилировать это в 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 более ограничен, чем С#, при перегрузке необязательных параметров.

Ответ 2

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

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

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

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

public static void TestFunc(int val1)     
{     
}  

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

TestFunc(1)

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

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

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

Примечание. Используя эту версию, VB IS может устранить, какой метод вызывать.

Ответ 3

Изменить

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

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 может преобразовать целое число в строку.

Ответ 4

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

Ответ 5

В Visual Basic Language Specification 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 неоднозначна.

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