8

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

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
}
  1. 为什么,由于类型不是静态已知的,它不解决重载接受dynamic
  2. 甚至可以使用重载方法dynamic吗?
  3. 解决此问题的最佳方法是什么?
4

2 回答 2

5

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

  1. 该方法的参数是一个零参数的 lambda。这给了我们所有三个重载的可能性。
  2. lambda 的主体返回dynamic. 因为存在从dynamic任何其他类型的隐式转换,所以我们现在知道所有三个重载都是好的。
  3. 尝试选择最佳过载。在大多数情况下,“最佳”是指派生最多的类型。因为intstring都派生自,所以和object的重载被认为是最好的。intstring
  4. 我们现在有两个“最佳”重载,这意味着编译器实际上不能选择其中一个。编译失败。

现在,关于您的问题的可能解决方案:

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

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

    或者

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

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

    M(() => (object)DynamicObject())
    
于 2011-08-26T21:00:51.270 回答
1

根据 MSDN 中的定义:

动态的

在大多数情况下,动态类型的行为类似于类型对象。但是,包含动态类型表达式的操作不会被编译器解析或类型检查。编译器将有关操作的信息打包在一起,这些信息稍后用于在运行时评估操作。作为该过程的一部分,动态类型的变量被编译为对象类型的变量。因此,动态类型只存在于编译时,而不存在于运行时

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

事实上,如果你这样做:

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与必须转换的类型不同。

于 2011-08-26T20:20:49.073 回答