为什么这个看似正确的.net代码不能编译?

本文关键字:代码 net 不能 编译 为什么 | 更新日期: 2023-09-27 18:12:17

我是在问,以防我错过了一些明显的东西,但我想我可能偶然发现了。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'是二义性的,因为在类' classlibrary . class1 '中存在多种具有此名称的成员。

为什么它会认为这个方法有歧义?只有一个Class1。带有(int, int)签名的TestFunc。这是一个错误,还是我错过了什么?

为什么这个看似正确的.net代码不能编译?

最终,这似乎归结为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能够消除调用哪个方法的歧义。

如果你尝试在VB中编译这个。你会得到

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#更受限制。

TestFunc是不明确的,因为默认参数。当TestFunc(x)被调用时,它不确定它是调用TestFunc与单个参数还是TestFunc与默认的2个参数,第二个参数是默认的一个。

编辑

当这个问题第一次发布时:

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可以将整数转换为字符串

在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)