【问题标题】:Why cannot C# resolve the correct overload in this case?在这种情况下,为什么 C# 不能解决正确的重载?
【发布时间】:2015-02-25 00:43:50
【问题描述】:

我遇到了一个不明确的奇怪情况,但重载解析器不这么认为。考虑:

public static class Program
{
    delegate int IntDel();
    delegate string StringDel();

    delegate void ParamIntDel(int x);
    delegate void ParamStringDel(string x);

    static void Test(IntDel fun) { }
    static void Test(StringDel fun) { }
    static void ParamTest(ParamIntDel fun) { }
    static void ParamTest(ParamStringDel fun) { }

    static int X() { return 42; }
    static void PX(int x) { }

    public static void Main(string[] args)
    {
        ParamTest(PX); // OK
        Test(X); // Ambiguos call!
    }
}

为什么对ParamTest 重载的调用被正确解析,而Test 重载却是模棱两可的?

【问题讨论】:

  • 编译器选择重载时不考虑方法的返回类型。调用方法时实际上不必使用返回值的自动结果。这里随便解决了,用Test(new IntDel(X));
  • 我相信 Java 和 C++ 也是如此。然而,这不是参数多态性的基本限制,例如在 Haskell 中,您可以根据返回类型进行重载。问题是允许对返回类型进行重载可能会导致类型推断出现一些问题。
  • Offtopic:我喜欢这些天几乎所有问题都会获得至少 1 票赞成票。 XD

标签: c# delegates overload-resolution


【解决方案1】:

也许是因为https://msdn.microsoft.com/en-us/library/aa691131%28v=vs.71%29.aspx

方法的签名明确地不包括返回类型,也不包括可能为最右边的参数指定的 params 修饰符。

IntDelStringDel 之间的唯一区别在于返回值。

更具体地说:https://msdn.microsoft.com/en-us/library/ms173171.aspx

在方法重载的上下文中,方法的签名不包括返回值。但在委托的上下文中,签名确实包括返回值。换句话说,方法必须具有与委托相同的返回类型。

【讨论】:

  • @Vilx- 添加了另一个参考,该参考明确说明了使用委托的方法重载。
  • 如何将int X() 视为IntDelStringDel
  • @HamletHakobyan 正确的问题是“如何将(ignorereturnvalue)X() 视为两者......”。显然它只能是两种委托类型中的一种,如果与另一种委托类型一起使用它会中断,但当时的编译器无法查看返回值类型。
  • 我认为这个问题需要更多解释才能被视为完全回答。
  • 为什么()=>X() 在这里不会引起歧义?
猜你喜欢
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
相关资源
最近更新 更多