2015-09-22 3 views
1

Я получаю RuntimeBinderException с сообщениемНазначение динамических свойств Броски RuntimeBinderException

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

Следующий код генерирует эту ошибку:

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

Почему для первых двух линий работы (оба типа возврата динамический) , но третий вызывает исключение (когда тип возвращаемого объекта является объектом)? У меня создалось впечатление, что при назначении динамическому связывание выполняется с использованием фактического типа времени выполнения правой стороны. Может ли кто-нибудь рассказать мне, почему третья строка не может работать так, как написано?

ответ

4

Тип времени компиляции выражения на RHS оператора = в течение первых двух линий dynamic. В первом случае это связано с тем, что вы набрали dynamic, а во втором случае это потому, что вы используете динамическое значение в одном из аргументов.

В третьем случае тип времени компиляции - object. Так что вы пытаетесь сделать эквивалент:

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

Это не работает, потому что нет неявного преобразования из object в SomeEnum?, которая является то, что компилятор пытается найти во время выполнения.

Обратите внимание, что элемент с нулевым значением действительно здесь не уместен - и не факт, что это перечисление. Просто оператор присваивания связан динамически, но использует время компиляции 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; 
+0

Разве это не тип времени компиляции RHS во втором примере 'object', а не' dynamic'? Вот где я застрял - второй и третий звонки кажутся такими же, как и во время компиляции «typeof». –

+0

@DStanley: Нет, потому что вызов динамически связан, потому что первый аргумент использует 'example'.Попробуйте назначить результат вместо 'var' и наведите указатель на объявление, и вы увидите: –

+0

@DStanley Нет, потому что example.EnumMember.GetType() возвращает' dynamic', поэтому выражение Enum.Parse должно, по определению, также возвращаем тип 'dynamic'. –

0

Вам все еще нужно сделать неявное преобразование для третьей линии

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

EDIT

Причина, по которой вам все еще нужно неявное преобразование происходит потому, что Enum.Parse возвращает объект. См. Документацию ниже.

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

+1

ОП знает об этом и спрашивает «почему?». –

+0

Проблема в том, что в реальном коде я не знаю типа 'SomeEnum', поэтому я не могу явно добавить этот приведение. Если вы знаете какой-то другой способ, не обращаясь к 'dynamic' или' SomeEnum', чтобы заставить задание работать, мне бы очень хотелось его изучить. –

+0

Спасибо @DStanley Я добавил изменение в свой ответ. – DPac

Смежные вопросы