2015-09-22 49 views
1

我得到一个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"); 
    } 
} 

为什么到前两行的工作(包括返回类型动态) ,但第三个抛出异常(当返回类型是对象)?我的印象是,当分配给动态时,绑定是使用右侧的实际运行时类型来执行的。有人可以请我指出,为什么第三行无法按书面形式运行?

回答

4

=操作者的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; 
+0

不是第二个例子'object'中的RHS的编译时类型,而不是'dynamic'?这就是我被卡住的地方 - 第二个和第三个调用与'typeof'的编译时解析不同。 –

+0

@DStanley:没有,因为这个调用是动态绑定的,因为第一个参数使用'example'。尝试将结果分配给'var',并将鼠标悬停在声明上,然后您会看到:) –

+0

@DStanley不,因为example.EnumMember.GetType()返回'dynamic',所以Enum.Parse表达式必须根据定义,也返回类型'dynamic'。 –

0

您仍然需要为第三行

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

编辑

,你还需要隐式转换是因为Enum.Parse返回一个对象的原因做一个隐式转换。请参阅下面的文档。

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

+1

OP知道并且问“为什么?” –

+0

问题是,在真实代码中,我不知道“SomeEnum”类型,所以我不能明确添加该投射。如果你知道一些其他的方法,而不需要使用'dynamic'或'SomeEnum'来完成任务,我很乐意学习它。 –

+0

谢谢@DStanley我在我的答案中添加了一个编辑。 – DPac