// Объявить одиночный динамический элемент данных по имени t
.
dynamic t = "Hello!";
Console.WriteLine("t is of type: {0}", t.GetType);
t = false;
Console.WriteLine("t is of type: {0}", t.GetType);
t = new List<int>;
Console.WriteLine("t is of type: {0}", t.GetType);
}
Вот
вывод:
t is of type: System.String
t is of type: System.Boolean
t is of type: System.Collections.Generic.List`1[System.Int32]
Имейте в виду, что приведенный выше код успешно скомпилировался и дал бы идентичный результат, если бы переменная
t
была объявлена с типом
System.Object
. Однако, как вскоре будет показано, ключевое слово
dynamic
предлагает много дополнительных возможностей.
Вызов членов на динамически объявленных данных
Учитывая то, что динамическая переменная способна принимать идентичность любого типа на лету (подобно переменной типа
System.Object
), у вас может возникнуть вопрос о способе обращения к членам такой переменной (свойствам, методам, индексаторам, событиям и т.п.). С точки зрения синтаксиса отличий нет. Нужно просто применить операцию точки к динамической переменной, указать открытый член и предоставить любые аргументы (если они требуются).
Но (и это очень важное "но") допустимость указываемых членов компилятор проверять не будет! Вспомните, что в отличие от переменной, определенной с типом
System.Object
, динамические данные не являются статически типизированными. Вплоть до времени выполнения не будет известно, поддерживают ли вызываемые динамические данные указанный член, переданы ли корректные параметры, правильно ли записано имя члена, и т.д. Таким образом, хотя это может показаться странным, следующий метод благополучно скомпилируется:
static void InvokeMembersOnDynamicData
{
dynamic textData1 = "Hello";
Console.WriteLine(textData1.ToUpper);
// Здесь можно было бы ожидать ошибки на этапе компиляции!
RuntimeBinderException: string не содержит определения для toupper
Другое очевидное отличие между обращением к членам динамических и строго типизированных данных связано с тем, что когда к элементу динамических данных применяется операция точки, ожидаемое средство IntelliSense среды Visual Studio не активизируется. Взамен IDE-среда позволит вводить любое имя члена, какое только может прийти вам на ум.
Отсутствие возможности доступа к средству IntelliSense для динамических данных должно быть понятным. Тем не менее, как вы наверняка помните, это означает необходимость соблюдения предельной аккуратности при наборе кода C# для таких элементов данных. Любая опечатка или символ в неправильном регистре внутри имени члена приведет к ошибке времени выполнения, в частности к генерации исключения типа
RuntimeBinderException
.
Класс
RuntimeBinderException
представляет ошибку, которая будет сгенерирована при попытке обращения к несуществующему члену динамического типа данных (как в случае
toupper
и
Foo
). Та же самая ошибка будет инициирована, если для члена, который существует, указаны некорректные данные параметров.
Поскольку динамические данные настолько изменчивы, любые обращения к членам переменной, объявленной с ключевым словом