【问题标题】:Dynamic Property Assignment Throws RuntimeBinderException动态属性分配引发 RuntimeBinderException
【发布时间】:2015-09-22 17:17:14
【问题描述】:

我收到了带有消息的RuntimeBinderException

无法将类型“object”隐式转换为“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");
    }
}

为什么前两行有效(均返回类型为动态),但第三行抛出异常(当返回类型为对象时)?我的印象是,当分配给动态时,绑定是使用右侧的实际运行时类型执行的。有人可以请教我为什么第三行无法按所写的那样运行吗?

【问题讨论】:

    标签: c# dynamic


    【解决方案1】:

    前两行= 运算符的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;
    

    【讨论】:

    • 第二个例子中RHS的编译时类型不是object,不是dynamic吗?这就是我被卡住的地方 - 除了typeof 的编译时分辨率之外,第二次和第三次调用似乎相同。
    • @DStanley:不,因为调用是动态绑定的,因为第一个参数使用example。尝试将结果分配给var,然后将鼠标悬停在声明上,您会看到:)
    • @DStanley 否,因为 example.EnumMember.GetType() 返回 dynamic,因此根据定义,Enum.Parse 表达式也必须返回类型 dynamic
    • 啊。这就是区别。知道了。谢谢。
    【解决方案2】:

    你还需要为第三行做一个隐式转换

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

    编辑

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

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

    【讨论】:

    • OP 知道这一点并在问“为什么?”
    • 问题是在实际代码中,我不知道SomeEnum 的类型,所以我无法显式添加该演员表。如果您知道其他方法,而不需要转换为 dynamicSomeEnum 来完成任务,我很乐意学习它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    相关资源
    最近更新 更多