Динамический тип
В C# версии 4.0, Microsoft представила новый тип: динамический. На самом деле это статический Тип, но в отличие от других статических типов, (потенциальные) члены динамического объекта не проверяются компилятором. Это даст вам некоторые преимущества динамически / слабо типизированных языков, при этом во всех других случаях сохраняя преимущества строго типизированного языка.
Объявление dynamic похоже на объявление любого другого типа-просто используйте ключевое слово dynamic вместо типа данных:
dynamic d1;
dynamic d2 = "A string";
dynamic d3 = 42;
Теперь у вас есть три разных объекта — первый на самом деле ничто в этой точке (null), в то время как второй является строкой и третьим целым числом. Интерпретатор автоматически решит это во время выполнения, основываясь на том, что вы назначаете переменной. Это также означает, что компилятор не будет проверять, что вы делаете с этими переменными, как показано в следующем примере:
dynamic d1;
dynamic d2 = "A string";
dynamic d3 = 42;
Console.WriteLine(d2.Length);
Console.WriteLine(d3.Length);
Строки имеют свойство length, чтобы определить длину строки, но целое число — нет. В этом случае я пытаюсь использовать это свойство для обеих переменных, и компилятор не будет жаловаться на это — если бы эти переменные были объявлены как строка и целое число, компилятор перехватил бы. Но поскольку типы являются динамическими, он просто компилируется и запускается. Однако, как только интерпретатор достигнет последней строки, будет выдано исключение, потому что очевидно, что вы не можете получить доступ к свойству, которое не существует.
Это также показывает опасность динамических типов — вы должны знать, что вы делаете, и убедиться, что вы правильно пишете каждое свойство и вызов метода, потому что компилятор не будет дважды проверять вашу работу, в основном позволяя публиковать код, который каждый раз терпит неудачу.
Динамический объект
Ключевое слово dynamic может, конечно же, быть использовано для более сложных типов данных нежели integer и string. Хороший тому пример, это когда оно используется для хранения анонимного объекта, как ниже:
dynamic user = new
Name = "John Doe",
Age = 42
>;
Console.WriteLine(user.Name + " is " + user.Age + " years old");
Это позволяет создать объект без предварительного определения класса. Ключевое словоdynamic можно использовать для его хранения, но также можно использовать ключевое слово var, которое может быть лучше подходит во многих ситуациях.
Вы можете подумать, что, поскольку тип является динамическим, вы можете просто добавить к нему свойства позже, например:
dynamic user = new
Name = "John Doe",
Age = 42
>;
user.HomeTown = "New York";
Поскольку проверка динамического типа во время компиляции не выполняется, этот код фактически выполняется, поскольку компилятор фактически не проверяет существование свойства HomeTown, но как только будет достигнута последняя строка, будет выдано исключение. Хотя динамический Тип очень динамичен, он не позволяет динамически добавлять в него новые свойства. Для этого можно использовать ExpandoObject, о котором мы поговорим в следующей статье.
Меняя тип
Переменная, объявленная как динамическая, вовсе не является бесттипной. Вместо этого C# будет рассматривать его внутренне как любой объект, присвоенный ему. В нашем самом первом примере вы увидите, как мы можем объявить переменную как динамическую, присвоить ей строку или целое число, а затем начать использовать свойства, принадлежащие этим типам. Однако вы можете легко изменить тип динамической переменной просто присвоить новое значение. Вот пример:
dynamic user = new
Name = «John Doe»,
Age = 42
>;
Console.WriteLine(user.GetType() + «: » + user.Name + » is » + user.Age + » years old»);
user = «Jane Doe»;
Console.WriteLine(user.GetType() + «: String.Length aelm5392″ data-element-id=»5392″ data-translation-ids=»» >Обратите внимание, как мы используем динамическую переменную user: сначала она содержит анонимный объект, а затем мы назначаем ему простую строку. Мы проверяем его с помощью метода gettype() C# для объектов, и в обоих случаях мы получаем доступ вариантов размещения найдено по установленному типу (имя/возраст свойствах анонимный объект, то свойство length строковых объектов).
Резюме
Ключевое слово dynamic позволяет использовать переменные, которые не зависят от типа, а действуют как тип данных, которые они содержат. Динамической переменной можно легко присвоить новое значение, и если тип присваиваемого значения отличается от текущего, динамическая переменная просто автоматически изменит тип.
Динамические переменные не проверяются компилятором, что позволяет получить доступ к свойствам, которые могут или не могут присутствовать. Это делает их очень гибкими, но также делает ваши приложения более уязвимыми к ошибкам. Именно по этой причине, вы можете ограничить использование динамических ключевых слов ситуациями, когда вы не можете выполнить то, что вы хотите, не используя его. Примеры, когда имеет смысл использовать ключевое слово dynamic, приведены для com-взаимодействия и при взаимодействии с форматами данных, такими как JSON и XML.
Is your preferred language not on the list? Click here to help us translate this article into your language!
Dynamic Language Runtime
Хотя C# относится к статически типизированным языкам, в последних версиях языка были добавлены некоторые динамические возможности. Так, начиная с .NET 4.0 была добавлена новая функциональность под названием DLR (Dynamic Language Runtime). DLR представляет среду выполнения динамических языков, например, таких языков как IronPython и IronRuby.
Чтобы понять значение данного нововведение, нужно осознавать разичие между языками со статической и динамической типизицией. В языках со статической типизацией выявление всех типов и их членов — свойств и методов происходит на этапе компиляции. А в динамических языках системе ничего не известно о свойствах и методах типов вплоть до выполнения.
Благодаря этой среде DLR C# может создавать динамические объекты, члены которых выявляются на этапе выполнения программы, и использовать их вместе с традиционными объектами со статической типизацией.
Ключевым моментом использования DLR в C# является применение типов dynamic . Это ключевое слово позволяет опустить проверку типов во время компиляции. Кроме того, объекты, объявленные как dynamic, могут в течение работы программы менять свой тип. Например:
dynamic obj = 3; // здесь obj - целочисленное int Console.WriteLine(obj); // 3 obj = "Hello world"; // obj - строка Console.WriteLine(obj); // Hello world obj = new Person("Tom", 37); // obj - объект Person Console.WriteLine(obj); // Person < Name = Tom, Age = 37 >record class Person(string Name, int Age);
Несмотря на то, что переменная x меняет тип своего значения несколько раз, данный код будет нормально работать. В этом использование типов dynamic отличается от применения ключевого слова var . Для переменной, объявленной с помощью ключевого слова var , тип выводится во время компиляции и затем во время выполнения больше не меняется.
Также можно найти общее между использованием dynamic и типом object. Если в предыдущем примере мы заменим dynamic на object: object x = 3; , то результат будет тот же. Однако и тут есть различия. Например:
object obj = 24; dynamic dyn = 24; obj += 4; // так нельзя dyn += 4; // а так можно
На строке obj += 4; мы увидим ошибку, так как операция += не может быть применена к типам object и int. С переменной, объявленной как dynamic, это пройдет, так как ее тип будет известен только во время выполнения.
Еще одна отличительная особенность использования dynamic состоит в том, что это ключевое слово применяется не только к переменным, но и к свойствам и методам. Например:
class Person < public string Name < get;>public dynamic Age < get; set; >public Person(string name, dynamic age) < Name = name; Age = age; >// выводим зарплату в зависимости от переданного формата public dynamic GetSalary(dynamic value, string format) < if (format == "string") return $"euro"; else if (format == "int") return value; else return 0.0; > public override string ToString() => $"Name: Age: "; >
В классе Person определено динамическое свойство Age, поэтому при задании значения этому свойству мы можем написать и person.Age=22 , и person.Age=»twenty-two» . Оба варианта будут допустимыми. А через параметр age в конструкторе этому свойству можно передать любое значение.
Также есть метод GetSalary , который возвращает значение dynamic. Например, в зависимости от параметра мы можем вернуть или строковое представление суммы дохода или численное. Также метод принимает dynamic в качестве параметра. Таким образом, мы можем передать в качестве значения дохода как целое, так и дробное число или строку. Посмотрим на конкретное применение:
dynamic tom = new Person("Tom", 22); Console.WriteLine(tom); Console.WriteLine(tom.GetSalary(28, "int")); dynamic bob = new Person("Bob", "twenty-two"); Console.WriteLine(bob); Console.WriteLine(bob.GetSalary("twenty-eight", "string"));
Консольный вывод программы:
Name: Tom Age: 22 28 Name: Bob Age: twenty-two twenty-eight euro