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;
See more on this question at Stackoverflow