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

时间:2014-09-17 13:47:10

标签: c# generics dynamic

我创建了一个class that inherits 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
        };
    }
}

用法:

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

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

2 个答案:

答案 0 :(得分:15)

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

从C#5规范,第7.6.5节:

  

如果至少满足下列条件之一,则动态绑定 invocation-expression

     
      
  • primary-expression 具有编译时类型dynamic
  •   
  • 可选参数列表的至少一个参数具有编译时类型dynamic,而 primary-expression 没有委托类型。< / LI>   
     

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

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

  • d is Foo始终为bool
  • d as Foo始终为Foo
  • new Foo(d)始终为Foo,即使在执行时确定要使用的确切构造函数

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

答案 1 :(得分:6)

动态是如何运作的。来自MSDN

  

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

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