【问题标题】:Passing dynamic object to C# method changes return type将动态对象传递给 C# 方法会更改返回类型
【发布时间】:2019-10-27 10:44:25
【问题描述】:

我创建了一个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 感到困惑?

【问题讨论】:

    标签: c# generics dynamic


    【解决方案1】:

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

    来自 C# 5 规范,第 7.6.5 节:

    如果以下至少一项成立,则 invocation-expression 是动态绑定的:

    • primary-expression 具有编译时类型dynamic
    • 可选argument-list 的至少一个参数具有编译时类型dynamic,而primary-expression 没有委托类型。

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

    几个操作涉及动态值,它们仍然具有非动态的整体类型。例如:

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

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

    【讨论】:

      【解决方案2】:

      这就是动态的工作原理。来自MSDN

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-20
        • 1970-01-01
        • 2023-03-09
        相关资源
        最近更新 更多