我问的是,如果我遗漏了一些明显的东西,但我想我可能偶然发现了.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'中存在多种具有此名称的成员。
为什么它会将此方法视为含糊不清?只有一个带有(int,int)签名的Class1.TestFunc。这是一个错误,还是我错过了什么?
答案 0 :(得分:23)
最终,它似乎归结为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能够消除要调用的方法的歧义。
答案 1 :(得分:15)
如果您尝试在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 :(得分: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可以将整数转换为字符串。
答案 3 :(得分:2)
由于默认参数,TestFunc不明确。当调用TestFunc(x)时,它不确定它是使用单个参数调用TestFunc还是使用默认2参数调用TestFunc第二个参数是默认值。
答案 4 :(得分:2)
在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
不明确。
我在C#规范中找不到任何说明可选参数被视为具有多个签名的方法的内容。从你看到的行为我假设在C#中它们不被认为有多个签名,否则你会得到编译器错误 - 这意味着它在C#中是有效的。我假设C#将根据某些规则选择被调用的方法,因为它不能同时调用TestFunc(0)
。