使用动态参数的方法重载解析

时间:2011-08-26 20:07:30

标签: c# dynamic overloading overload-resolution

之前可能已经回答过了。我看到许多“动态方法重载解析”问题,但没有一个专门处理传递dynamic参数。在以下代码中,Test中无法解析对M的最后一次调用(无法编译)。错误是: [{1}} 的前两个重载之间的调用是不明确的。

M
  1. 为什么,因为类型不是静态知道的,它是否解决了接受static void M(Func<int> f) { } static void M(Func<string> f) { } static void M(Func<dynamic> f) { } static dynamic DynamicObject() { return new object(); } static void Test() { M(() => 0); M(() => ""); M(() => DynamicObject()); //doesn't compile } 的重载?
  2. 重载方法甚至可以使用dynamic
  3. 解决此问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:5)

这里的问题是类型推断。编译器试图根据参数找出要使用的重载,但它也试图根据所选的重载找出参数的类型。在M(() => DynamicObject())的情况下,过程如下:

  1. 该方法的参数是一个零参数的lambda。这给了我们所有三种重载作为可能性。
  2. lambda的主体返回dynamic。因为存在从dynamic到任何其他类型的隐式转换,我们现在知道所有三个重载都是好的。
  3. 尝试选择最佳过载。在大多数情况下,“最佳”意味着最衍生的类型。由于intstring都来自object,因此intstring的重载最佳。
  4. 我们现在有两个“最佳”重载,这意味着编译器实际上无法选择其中一个。编译失败。
  5. 现在,关于问题的可能解决方案:

    1. 使用强制转换或类型化局部变量使lambda的类型显式:

      M((Func<dynamic>)(() => DynamicObject()));
      

      Func<dynamic> f = () => DynamicObject();
      M(f);
      
    2. 将动态重载重命名为DynamicM。这样,您就不必处理重载决策。

    3. 这个对我来说有些不对劲:通过强制转换为dynamic,确保object重载是唯一合适的:

      M(() => (object)DynamicObject())
      

答案 1 :(得分:1)

从MSDN中的定义:

dynamic

  

在大多数情况下,类型动态的行为类似于对象。然而,   包含动态类型表达式的操作未解析   或由编译器检查的类型。编译器打包在一起   有关操作的信息,以及稍后使用的信息   在运行时评估操作。作为过程的一部分,变量   类型为dynamic的数据被编译为object类型的变量。因此,   type dynamic仅在编译时存在,而不是在运行时

编译时不存在动态,因为它需要将其转换为目的地 *类型*,这就是为什么无法解决它。什么是目的地类型?

事实上,如果你做这样的事情:

static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<object> f) { } // could be also declared like dynamic here, works by the way

static object DynamicObject()
{
    return new object();
}

static void Test()
{
    M(() => 0);
    M(() => "");
    M(() => DynamicObject());
}

它完全可以正常工作,因为object就像已经在编译时的类型一样,不同于dynamic类型,必须转换