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?

Jon Skeet
people
quotationmark

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;

people

See more on this question at Stackoverflow