将动态对象传递给C#方法会更改返回类型

Jim*_*uck 20 c# generics dynamic

我创建了一个继承DynamicObject并希望创建静态方法的类,该方法可以创建具有预定属性(存储在其中Dictionary)的新实例.

public class CustomDynamic : DynamicObject
{
    protected Dictionary<string, object> InnerDictionary;

    public static T Create<T>(Dictionary<string, object> dictionary) where T : CustomDynamic , new()
    {
        return new T
        {
            InnerDictionary = dictionary
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

dynamic d = new Dictionary<string, object>();

var realPlayer = CustomDynamic.Create<Player>(d as Dictionary<string, object>);
var dynaPlayer = CustomDynamic.Create<Player>(d);

realPlayer // Player type according to VS2013
dynaPlayer // dynamic type according to VS2013
Run Code Online (Sandbox Code Playgroud)

由于只有一个方法签名,为什么传递动态返回动态对象?或者实际上只是Visual Studio 2013变得困惑?

Jon*_*eet 20

这是因为几乎任何涉及动态值的操作都会在执行时动态解析.对于实际上在编译时只存在一种方法的情况,没有例外; 这种语言更简单.(对于某些调用,编译器在编译时确实执行了足够的分辨率,以确保至少有一个方法具有适当数量的参数 - 这在7.5.4节的C#5规范中指定,但是没有影响有效回报类型.)

从C#5规范,第7.6.5节:

一个调用表达式如果以下中的至少一个保持动态绑定:

  • 基本表达式具有编译时类型dynamic.
  • 可选参数列表的至少一个参数具有编译时类型dynamic,而primary-expression没有委托类型.

在这种情况下,编译器将invocation-expression分类为type的值dynamic.[...]

一些涉及动态值的操作仍然具有非动态整体类型.例如:

  • d is Foo 总是 bool
  • d as Foo 总是 Foo
  • new Foo(d)Foo即使在执行时确定要使用的确切构造函数,也总是如此

但任何方法调用都被视为具有返回类型dynamic.


Sel*_*enç 7

这是动态的运作方式.来自MSDN

如果方法调用中的一个或多个参数具有动态类型,或者方法调用的接收方是动态类型,则在运行时而不是在编译时发生重载分辨率.

您可能认为您的方法没有任何额外的重载,但您可能有.编译器不会在编译时执行该检查,因此您可以将类型dynaPlayer视为动态而不是Player.