Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果添加方法不会';不要卷入模棱两可的事情_C#_Overload Resolution - Fatal编程技术网

C# 如果添加方法不会';不要卷入模棱两可的事情

C# 如果添加方法不会';不要卷入模棱两可的事情,c#,overload-resolution,C#,Overload Resolution,我有这门课 public class Overloaded { public void ComplexOverloadResolution(params string[] something) { Console.WriteLine("Normal Winner"); } public void ComplexOverloadResolution<M>(M something) { Console.WriteL

我有这门课

public class Overloaded
{
    public void ComplexOverloadResolution(params string[] something)
    {
        Console.WriteLine("Normal Winner");
    }

    public void ComplexOverloadResolution<M>(M something)
    {
        Console.WriteLine("Confused");
    }
}
它将
Normal Winner
写入控制台

但是,如果我添加另一种方法:

    public void ComplexOverloadResolution(string something, object somethingElse = null)
    {
        Console.WriteLine("Added Later");
    }
我得到以下错误:

以下方法或属性之间的调用不明确:>'
重载.ComplexOverloadResolution(params string[])
'和'
重载.ComplexOverloadResolution(string)
'

我可以理解,添加一个方法可能会引入调用歧义,但这是已经存在的两个方法之间的歧义
(params string[])
(string)
!显然,歧义中涉及的两种方法都不是新添加的方法,因为第一种是params,第二种是泛型


这是虫子吗?规范的哪一部分说明应该是这种情况?

如果从第一个方法中删除
参数,则不会发生这种情况。第一个和第三个方法都有有效的调用
ComplexOverloadResolution(string)
,但如果第一个方法是
public void ComplexOverloadResolution(string[]something)
,则不会有歧义

为参数
对象somethingElse=null提供值使其成为可选参数,因此在调用重载时不必指定该参数

编辑:编译器正在做一些疯狂的事情。如果在第一个方法之后移动代码中的第三个方法,它将正确报告。因此,它似乎在使用前两个重载并报告它们,而没有检查正确的重载

“ConsoleApplication1.Program.ComplexOverloadResolution(参数字符串[])”和 'ConsoleApplication1.Program.ComplexOverloadResolution(字符串,对象)'

编辑2:新发现。从上述三种方法中删除任何方法都不会在两者之间产生歧义。因此,冲突似乎只有在存在三种方法时才会出现,而不管顺序如何

规范的哪一部分说应该是这样的

第7.5.3节(重载解析),以及第7.4节(成员查找)和第7.5.2节(类型推断)

请特别注意第7.5.3.2节(更好的函数成员),其中部分说明“从参数列表中删除没有相应参数的可选参数”,以及“如果M(p)是非泛型方法,且M(q)是泛型方法,则M(p)优于M(q)。”

然而,我对规范的这些部分理解不够透彻,无法知道规范的哪些部分控制着这种行为,更不用说判断它是否符合规范

  • 如果你写信

    var blah = new Overloaded();
    blah.ComplexOverloadResolution("Which wins?");
    
    或者只是写

    var blah = new Overloaded();
    blah.ComplexOverloadResolution();
    
    它最终将转换为相同的方法,在方法中

    public void ComplexOverloadResolution(params string[] something
    
    这是因为
    params
    关键字使得它与未指定参数时的情况最匹配

  • var blah = new Overloaded();
    blah.ComplexOverloadResolution(); // will be ComplexOverloadResolution(params string[] something) function called here, like a best match.
    
  • 如果您尝试添加一个或多个这样的新方法

    public void ComplexOverloadResolution(string something)
    {
        Console.WriteLine("Added Later");
    }
    
    它将完美地编译并调用此方法,因为它是
    字符串
    参数调用的完美匹配。比
    params string[]something
    强得多

  • 您像以前一样声明了第二个方法

    public void ComplexOverloadResolution(string something, object something=null);
    
    编译器,在第一个方法和这个方法之间完全混淆,只是添加了一个。 因为它不知道他现在应该在你的电话里

    var blah = new Overloaded();
    blah.ComplexOverloadResolution("Which wins?");
    
    事实上,如果您从调用中删除字符串参数,就像下面的代码一样,一切都会正确编译并像以前一样工作

    var blah = new Overloaded();
    blah.ComplexOverloadResolution(); // will be ComplexOverloadResolution(params string[] something) function called here, like a best match.
    
  • 这是虫子吗

    恭喜,您在重载解析中发现了一个错误。这种虫子在C#4和C#5中繁殖;它不会在语义分析器的“Roslyn”版本中重现。我已经通知了C#5测试团队,希望我们能在最终发布之前调查并解决这个问题。(一如既往,没有承诺。)

    正确的分析如下。候选人包括:

    0: C(params string[]) in its normal form
    1: C(params string[]) in its expanded form
    2: C<string>(string) 
    3: C(string, object) 
    
    0:C(参数字符串[])的正常形式
    1:C(参数字符串[])的展开形式
    2:C(字符串)
    3:C(字符串、对象)
    
    候选零显然不适用,因为
    string
    不能转换为
    string[]
    。剩下三个

    在这三种方法中,我们必须确定一种独特的最佳方法。我们通过对剩下的三位候选人进行两两比较来做到这一点。有三对这样的。一旦我们去掉省略的可选参数,所有这些参数都有相同的参数列表,这意味着我们必须进入本规范第7.5.3.2节中所述的高级平分回合

    哪一个更好,1还是2?相关的分界点是泛型方法总是比非泛型方法差。2比1差。所以2不可能是赢家

    哪一个更好,1还是3?相关的分界点是:仅适用于其扩展形式的方法总是比适用于其正常形式的方法更差。因此1比3差。所以1不可能是赢家

    2号还是3号,哪个更好?相关的分界点是泛型方法总是比非泛型方法差。2比3差。所以2不可能是赢家

    要从一组多个适用的候选人中选择,候选人必须(1)不败,(2)击败至少一个其他候选人,以及(3)具有前两个属性的唯一候选人。候选人三未被其他候选人击败,且至少击败一名其他候选人;它是唯一具有此属性的候选者。因此,候选人三是最佳人选。它应该赢

    不仅是C#4编译器出错了,正如您正确地注意到的,它还报告了一条奇怪的错误消息。编译器将重载解析分析搞错了,这有点令人惊讶。它错误地接收到错误信息完全不令人惊讶;如果无法确定最佳方法,则“模糊方法”错误启发式基本上从候选集中选择任意两种方法。它不太善于找到它
    public class Overloaded
    {
        public void ComplexOverloadResolution(params string[] somethings)
        {
            Console.WriteLine("Normal Winner");
        }
    
        public void ComplexOverloadResolution<M>(M something)
        {
            Console.WriteLine("Confused");
        }
    
        public void ComplexOverloadResolution(string something, object somethingElse = null)
        {
            Console.WriteLine("Added Later");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Overloaded a = new Overloaded();
            a.ComplexOverloadResolution(something:"asd");
        }
    }