动态属性分配引发RuntimeBinderException

时间:2015-09-22 17:17:14

标签: c# dynamic

我收到RuntimeBinderException消息

  

无法隐式转换类型'对象'到'MyNamespace.SomeEnum?'。存在显式转换(您是否错过了演员?)

以下代码生成该错误:

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");
    }
}

为什么前两行有效(两者都返回动态),但第三行抛出异常(返回类型为对象时)?我的印象是,在分配到动态时,使用右侧的实际运行时类型执行绑定。有人可以告诉我为什么第三行无法按照书面形式运行?

2 个答案:

答案 0 :(得分:4)

前两行的=运算符的RHS上的表达式的编译时类型是dynamic。在第一种情况下,因为您已投放到dynamic,而在第二种情况下,因为您在其中一个参数中使用了动态值。<\ n / p>

在第三种情况下,表达式的编译时类型为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;

答案 1 :(得分:0)

您仍然需要对第三行进行隐式转换

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

修改

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

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