Хотя C# относится к статически типизированным языкам, в последних версиях языка были добавлены некоторые динамические возможности. Так, начиная с .NET 4.0 была добавлена новая функциональность под названием DLR (Dynamic Language Runtime). DLR представляет среду выполнения динамических языков, например, таких языков как IronPython и IronRuby.
Чтобы понять значение данного нововведение, нужно осознавать разичие между языками со статической и динамической типизицией. В языках со статической типизацией выявление всех типов и их членов — свойств и методов происходит на этапе компиляции. А в динамических языках системе ничего не известно о свойствах и методах типов вплоть до выполнения.
Благодаря этой среде DLR C# может создавать динамические объекты, члены которых выявляются на этапе выполнения программы, и использовать их вместе с традиционными объектами со статической типизацией.
Ключевым моментом использования DLR в C# является применение типов dynamic. Это ключевое слово позволяет опустить проверку типов во время компиляции. Кроме того, объекты, объявленные как dynamic, могут в течение работы программы менять свой тип. Например:
class Program
{
static void Main(string[] args)
{
dynamic x = 3; // здесь x - целочисленное int
Console.WriteLine(x);
x = "Привет мир"; // x - строка
Console.WriteLine(x);
x = new Person() { Name = "Tom", Age = 23 }; // x - объект Person
Console.WriteLine(x);
Console.ReadLine();
}
}
class Person
{
public string Name {get;set;}
public int Age { get; set; }
public override string ToString()
{
return Name + ", " + Age.ToString();
}
}
Несмотря на то, что переменная 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;set;}
public dynamic Age { get; set; }
// выводим зарплату в зависимости от переданного формата
public dynamic getSalary(dynamic value, string format)
{
if (format=="string")
{
return value + " рублей";
}
else if (format == "int")
{
return value;
}
else
{
return 0.0;
}
}
public override string ToString()
{
return Name + ", " + Age.ToString();
}
}
В классе Person определено динамическое свойство Age, поэтому при задании значения этому свойству мы можем написать и person.Age=33
, и person.Age="тридцать три"
. Оба варианта будут правильными.
Также есть метод getSalary
, возвращающий значение dynamic. Например, в зависимости от параметра мы можем вернуть или строковое представление суммы дохода или численное. Также метод принимает dynamic в качестве параметра. Таким образом, мы можем передать в качестве значения дохода как целое, так и дробное число. Посмотрим на конкретное применение:
dynamic person1 = new Person() { Name = "Том", Age = 27 };
Console.WriteLine(person1);
Console.WriteLine(person1.getSalary(28.09, "int"));
dynamic person2 = new Person() { Name = "Билл", Age = "Двадцать два года" };
Console.WriteLine(person2);
Console.WriteLine(person2.getSalary(30, "string"));