动态 属性 赋值抛出 RuntimeBinderException

Dynamic Property Assignment Throws RuntimeBinderException

我收到 RuntimeBinderException 消息

Cannot implicitly convert type 'object' to 'MyNamespace.SomeEnum?'. An explicit conversion exists (are you missing a cast?)

以下代码会生成该错误:

public enum SomeEnum
{
    Val1
}

public class Example
{
    public SomeEnum? EnumMember { get; set; }
}

public static class Program
{
    static void Main()
    {
        dynamic example = new Example();

        // Works without issue
        example.EnumMember = (dynamic)Enum.Parse(typeof(SomeEnum), "Val1");

        // Works without issue
        example.EnumMember = Enum.Parse(example.EnumMember.GetType(), "Val1");

        // Throws the aforementioned RuntimeBinderException
        example.EnumMember = Enum.Parse(typeof(SomeEnum), "Val1");
    }
}

为什么前两行有效(都是 return 动态类型),但第三行抛出异常(当 return 类型是对象时)?我的印象是,当分配给动态时,绑定是使用右侧的实际 运行 时间类型执行的。有人能告诉我为什么第三行不能运行吗?

第三行还需要隐式转换

example.EnumMember = (SomeEnum) Enum.Parse(typeof(SomeEnum), "Val1");

编辑

您仍然需要隐式转换的原因是因为 Enum.Parse returns 一个对象。请参阅下面的文档。

https://msdn.microsoft.com/en-us/library/essfb559(v=vs.110).aspx

前两行 = 运算符的 RHS 表达式的编译时类型是 dynamic。在第一种情况下,这是因为您已强制转换为 dynamic,而在第二种情况下,这是因为您在其中一个参数中使用了动态值。

在第三种情况下,表达式的编译时类型是object。所以你试图做相当于:

object x = Enum.Parse(typeof(SomeEnum), "Val1");
example.EnumMember = x;

那行不通,因为没有从 objectSomeEnum? 隐式 转换,这是编译器在执行时试图找到的时间。

请注意,可空性部分在这里确实不相关——它是一个枚举也与此无关。只是赋值运算符是动态绑定的,但是使用 RHS 的编译时时间。这是一个类似但更简单的示例:

class Test
{
    public int Foo { get; set; }

    static void Main()
    {
        dynamic example = new Test();

        example.Foo = 10; // Fine

        object o = 10;
        example.Foo = o; // Bang
    }
}

如果您希望编译器使用返回值的 实际 类型而不是编译时类型动态处理赋值,那么使用 dynamic 正好你想做什么 - 要么转换为动态,要么使用:

dynamic value = ...;
target.SomeProperty = value;