之前可能已经回答过了。我看到许多“动态方法重载解析”问题,但没有一个专门处理传递dynamic
参数。在以下代码中,Test
中无法解析对M
的最后一次调用(无法编译)。错误是: [{1}} 的前两个重载之间的调用是不明确的。
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
}
的重载? dynamic
?答案 0 :(得分:5)
这里的问题是类型推断。编译器试图根据参数找出要使用的重载,但它也试图根据所选的重载找出参数的类型。在M(() => DynamicObject())
的情况下,过程如下:
dynamic
。因为存在从dynamic
到任何其他类型的隐式转换,我们现在知道所有三个重载都是好的。int
和string
都来自object
,因此int
和string
的重载最佳。现在,关于问题的可能解决方案:
使用强制转换或类型化局部变量使lambda的类型显式:
M((Func<dynamic>)(() => DynamicObject()));
或
Func<dynamic> f = () => DynamicObject();
M(f);
将动态重载重命名为DynamicM
。这样,您就不必处理重载决策。
这个对我来说有些不对劲:通过强制转换为dynamic
,确保object
重载是唯一合适的:
M(() => (object)DynamicObject())
答案 1 :(得分:1)
从MSDN中的定义:
在大多数情况下,类型动态的行为类似于对象。然而, 包含动态类型表达式的操作未解析 或由编译器检查的类型。编译器打包在一起 有关操作的信息,以及稍后使用的信息 在运行时评估操作。作为过程的一部分,变量 类型为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
类型,必须转换。