Передача динамического объекта методу С# возвращает тип возврата
Я создал класс, который наследует DynamicObject
и хочет создать статический метод, который может создавать новые экземпляры с заранее определенными свойствами (хранимыми в Dictionary
).
public class CustomDynamic : DynamicObject
{
protected Dictionary<string, object> InnerDictionary;
public static T Create<T>(Dictionary<string, object> dictionary) where T : CustomDynamic , new()
{
return new T
{
InnerDictionary = dictionary
};
}
}
Применение:
dynamic d = new Dictionary<string, object>();
var realPlayer = CustomDynamic.Create<Player>(d as Dictionary<string, object>);
var dynaPlayer = CustomDynamic.Create<Player>(d);
realPlayer // Player type according to VS2013
dynaPlayer // dynamic type according to VS2013
Поскольку существует только одна сигнатура метода, почему передача в динамическом возврате динамического объекта? Или на самом деле просто Visual Studio 2013 запутался?
Ответы
Ответ 1
Это связано с тем, что почти любая операция, включающая динамическое значение, динамически решается во время выполнения. Исключений не существует для случаев, когда на момент компиляции присутствует только один метод; язык проще. (Для некоторых вызовов компилятор выполняет достаточное разрешение во время компиляции, чтобы гарантировать, что существует хотя бы один метод с подходящим количеством параметров - это указано в спецификации С# 5 в разделе 7.5.4, но это не влияют на эффективный тип возврата.)
Из спецификации С# 5, раздел 7.6.5:
Вызывающее выражение динамически связано, если выполняется хотя бы одно из следующих условий:
- Первичное выражение имеет
dynamic
типа компиляции. - По крайней мере, один аргумент необязательного аргумента-списка имеет
dynamic
тип времени компиляции, а первичное выражение не имеет тип делегата.
В этом случае компилятор классифицирует выражение invocation как значение типа dynamic
. [...]
Существует несколько операций с динамическими значениями, которые по-прежнему имеют нединамический общий тип. Например:
-
d is Foo
всегда bool
-
d as Foo
всегда Foo
-
new Foo(d)
всегда Foo
хотя точный конструктор для использования определяется во время выполнения
Но любой вызов метода обрабатывается как возвращаемый тип dynamic
.
Ответ 2
Это динамично работает. Из MSDN
Разрешение перегрузки происходит во время выполнения, а не во время компиляции, если один или несколько аргументов в вызове метода имеют динамический тип или если получатель вызова метода имеет тип dynamic.
Вы можете подумать, что у вас нет дополнительных перегрузок для вашего метода, но у вас может быть. Компилятор не выполняет эту проверку во время компиляции, поэтому вы видите тип dynaPlayer
как динамический, а не Player
.