ситуация во время выполнения.
В приведенном ниже примере программы применение типа dynamic демонстрируется на практике.
// Продемонстрировать применение типа dynamic, using System;
using System.Globalization;
class DynDemo {
static void Main() {
// Объявить две динамические переменные, dynamic str; dynamic val;
// Поддерживается неявное преобразование в динамические типы.
// Поэтому следующие присваивания вполне допустимы, str = 'Это строка'; val = 10;
Console.WriteLine('Переменная str содержит: ' + str);
Console.WriteLine('Переменная val содержит: ' + val + ' ');
str = str.ToUpper (Culturelnfo.CurrentCulture);
Console.WriteLine('Переменная str теперь содержит: ' + str);
val = val + 2;
Console.WriteLine('Переменная val теперь содержит: ' + val + ' ');
string str2 = str.ToLower(Culturelnfo.CurrentCulture);
Console.WriteLine('Переменная str2 содержит: ' + str2);
// Поддерживаются неявные преобразования из динамических типов.
int х = val * 2;
Console.WriteLine('Переменная x содержит: ' + x);
}
}
Выполнение этой программы дает следующий результат.
Переменная str содержит: Это строка Переменная val содержит: 10
Переменная str теперь содержит: ЭТО СТРОКА Переменная val теперь содержит: 12
Переменная str2 содержит: это строка Переменная х содержит: 24
Обратите внимание в этой программе на две переменные str и val, объявляемые с помощью типа dynamic. Это означает, что проверка на соответствие типов операций с участием обеих переменных не будет произведена во время компиляции. В итоге для них оказывается пригодной любая операция. В данном случае для переменной str вызываются методы ToUpper () и ToLower () класса String, а переменная участвует в операциях сложения и умножения. И хотя все перечисленные выше действия совместимы с типами объектов, присваиваемых обеим переменным в рассматриваемом здесь примере, компилятору об этом ничего не известно — он просто принимает. И это, конечно, упрощает программирование динамических процедур, хотя и допускает возможность Появления ошибок в подобных действиях во время выполнения.
В разбираемом здесь примере программа ведет себя 'правильно' во время выполнения, поскольку объекты, присваиваемые упомянутым выше переменным, поддерживают действия, выполняемые в программе. В частности, переменной val присваивается целое значение, и поэтому она поддерживает такие целочисленные операции, как сложение. А переменной str присваивается символьная строка, и поэтому она поддерживает строковые операции. Следует, однако, иметь в виду, что ответственность за фактическую поддержку типом объекта, на который делается ссылка, всех операций над данными типа dynamic возлагается на самого программирующего. В противном случае выполнение программы завершится аварийным сбоем.
В приведенном выше примере обращает на себя внимание еще одно обстоятельство: переменной типа dynamic может быть присвоен любой тип ссылки на объект благодаря неявному преобразованию любого типа в тип dynamic. Кроме того, тип dynamic автоматически преобразуется в любой другой тип. Разумеется, если во время выполнения такое преобразование окажется неправильным, то произойдет ошибка
при выполнении. Так, если добавить в конце рассматриваемой здесь программы следующую строку кода:
bool b = val;
то возникнет ошибка при выполнении из-за отсутствия неявного преобразования типа int (который оказывается типом переменной val во время выполнения) в тип bool. Поэтому данная строка кода приведет к ошибке при выполнении, хотя она и будет скомпилирована безошибочно.
Прежде чем оставить данный пример программы, попробуйте поэкспериментировать с ней. В частности, измените тип переменных str и val на object, а затем попытайтесь скомпилировать программу еще раз. В итоге появятся ошибки при компиляции, поскольку тип object не поддерживает действия, выполняемые над обеими переменными, что и будет обнаружено во время компиляции. В этом, собственно, и заключается основное отличие типов object и dynamic. Несмотря на то что оба типа могут использоваться для ссылки на объект любого другого типа, над переменной типа object можно производить только те
