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

Dan*_*iel 8 c# overloading dynamic overload-resolution

这可能是之前已经回答过的.我看到很多"动态方法重载解析"问题,但没有一个专门处理传递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
}
Run Code Online (Sandbox Code Playgroud)
  1. 为什么,因为类型不是静态知道的,它是否解决了过载接受dynamic
  2. 是否可以使用重载方法dynamic
  3. 解决这个问题的最佳方法是什么?

svi*_*ick 5

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

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

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

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

    M((Func<dynamic>)(() => DynamicObject()));
    
    Run Code Online (Sandbox Code Playgroud)

    要么

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

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

    M(() => (object)DynamicObject())
    
    Run Code Online (Sandbox Code Playgroud)