1

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?

0

2 Answers 2

4

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;
Sign up to request clarification or add additional context in comments.

3 Comments

Isn't the compile-time type of the RHS in the second example object, not dynamic? That's where I was stuck - the second and third calls seem the same other than the compile-time resolution of typeof.
@DStanley: Nope, because the call is dynamically bound, because the first argument uses example. Try assigning the result to var instead and hover over the declaration and you'll see :)
@DStanley No, because example.EnumMember.GetType() returns dynamic, so the Enum.Parse expression must, by definition, also return type dynamic.
0

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

2 Comments

OP knows that and is asking "why?"
The problem is that in real code, I don't know the type SomeEnum, so I can't explicitly add that cast. If you know of some other way, without casting to dynamic or SomeEnum to get the assignment to work, I would love to learn it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.