简体   繁体   中英

Dynamic Property Assignment Throws RuntimeBinderException

I am getting a RuntimeBinderException with the message

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

The following code generates that error:

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

Why do to first two lines work (both return type dynamic), but the third throws an exception (when the return type is object)? I was under the impression that, when assigning to dynamic, the binding is performed using the actual, run-time type of the right-hand-side. Can someone please enlighten me as to why the third line is unable to run as written?

The compile-time type of the expression on the RHS of the = operator for the first two lines is dynamic . In the first case that's because you've cast to dynamic , and in the second case it's because you're using a dynamic value in one of the arguments.

In the third case, the compile-time type of the expression is object . So you're trying to do the equivalent of:

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

That doesn't work, because there's no implicit conversion from object to SomeEnum? , which is what the compiler is trying to find at execution time.

Note that the nullability part really isn't relevant here - nor is the fact that it's an enum. It's just that the assignment operator is being bound dynamically, but using the compile-time time of the RHS. Here's a similar but simpler example:

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
    }
}

If you want the compiler to handle the assignment dynamically using the actual type of the value returned rather than the compile-time type, then using dynamic is exactly what you want to do - either cast to dynamic, or use:

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

You still need to do an implicit conversion for the third line

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

EDIT

The reason that you still need implicit conversion is because Enum.Parse returns an object. Refer to the documentation below.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM