Есть ли способ проверить, является ли переменная динамической?
Следующий фрагмент кода всегда будет возвращать true, если переменная v
равна null
:
v is dynamic
и следующий тест не будет компилироваться ( "Оператор typeof не может использоваться для динамического типа" ):
v.GetType() == typeof(dynamic)
Итак, есть ли способ проверить, есть ли переменная dynamic
?
Ответы
Ответ 1
Во-первых, вам нужно отделить переменную и объект. Переменная динамическая , если она определена как dynamic
. Вот и все. Больше ничего. Поле или свойство будут аннотированы с помощью атрибута [Dynamic]
, то есть
public dynamic Foo {get;set;}
на самом деле:
[Dynamic]
public object Foo {get;set;}
Это в основном выступает как приглашение для компилятора получить доступ к объекту через API dynamic
, а не через API OOP.
Объект поддерживает полные возможности dynamic
, если он реализует IDynamicMetaObjectProvider
- однако к этому объекту можно получить доступ как через API dynamic
, так и через обычный API ООП (он может иметь оба). Точно так же объект, который не реализует IDynamicMetaObjectProvider
, может быть доступен через API (но: только публичные члены будут доступны через dynamic
).
Ответ 2
Нет типа CLR, называемого dynamic
. Компилятор С# делает все значения dynamic
типа object
, а затем вызывает код обязательной привязки, чтобы выяснить, как с ними справиться. Если был использован dynamic
, он будет отображаться как object
.
Но вы можете проверить, имеет ли экземпляр тип IDynamicMetaObjectProvider
, или вы можете проверить, реализует ли тип IDynamicMetaObjectProvider
Ответ 3
В динамике С# нет проверки времени выполнения, и она будет иметь тип другой стороны символа =. Однако GetType - это оценка времени выполнения, поэтому вы всегда будете получать объявленный тип, а не динамический.
Вы можете прочитать немного больше здесь: http://msdn.microsoft.com/en-us/magazine/gg598922.aspx
Ответ 4
Всегда будет существовать тип времени выполнения, как говорили другие.
Существует ошибка для обнаружения локальных переменных, полагаясь на то, что динамические переменные не поддерживают методы расширения.
static void DummyDynamicTest<T>(this T t) //extension method
{
}
dynamic test = 1;
try
{
test.DummyDynamicTest();
//not dynamic
}
catch (RuntimeBinderException)
{
//dynamic
}
Однако вы не можете реорганизовать функциональность в другой метод. Это не может быть очень полезно вообще в каких-либо значимых сценариях, игнорировать любой ценой.
Ответ 5
@nawfal К сожалению, ваш метод расширения не работает, когда передается какой-либо нормальный класс poco, который не является динамическим.
Предложение @Marc Gravell является правильным. Я думаю, что путаница заключается в том, что даже если вы можете заявить что-либо как динамическое. Однако, когда вы создаете экземпляр для конкретного класса, тогда он уже не является действительно динамичным. Вот некоторые тесты, которые я бросил на это. Только test2 и test3 должны пройти. Вы можете протестировать его, пытаясь установить какое-то свойство, которое не существует для каждой динамики. Это вызовет исключение из нединамической динамики.:)
class Program
{
private class MyDynamic: DynamicObject
{
}
static void Main(string[] args)
{
dynamic test1 = new { Name = "Tim" };
//although I used the dynamic keyword here, it is NOT dynamic. dynamics are only dynamics if they support dynamically adding properties
//uncommenting this line will cause an exception
//test.LastName = "Jones"
if (test1 is IDynamicMetaObjectProvider) { Console.WriteLine("test1"); }
dynamic test2 = new MyDynamic();
if (test2 is IDynamicMetaObjectProvider) { Console.WriteLine("test2"); }
dynamic test3 = new ExpandoObject();
if (test3 is IDynamicMetaObjectProvider) { Console.WriteLine("test3"); }
dynamic test4 = new List<string>();
if (test4 is IDynamicMetaObjectProvider) { Console.WriteLine("test4"); }
}
}