Поделиться через


Использование динамического типа

Тип dynamic является статическим типом, но объект типа dynamic проходит проверку статического типа. В большинстве случаев он работает как тип object. Компилятор предполагает, что dynamic элемент поддерживает любую операцию. Поэтому не нужно определить, получает ли объект значение из COM-API из динамического языка, например IronPython, из модели объектов HTML-документа (DOM), из отражения или из другого места в программе. Однако если код недействителен, возникают ошибки во время выполнения.

Например, если метод exampleMethod1 экземпляра в следующем коде имеет только один параметр, компилятор распознает, что первый вызов метода недействителен, ec.exampleMethod1(10, 4)так как он содержит два аргумента. Этот вызов приводит к ошибке компилятора. Компилятор не проверяет второй вызов метода, dynamic_ec.exampleMethod1(10, 4)так как тип dynamic_ec имеет значение dynamic. В результате ошибка компилятора не возникает. Однако ошибка не выходит заметок на неопределенный срок. Он отображается во время выполнения и вызывает исключение во время выполнения.

static void Main(string[] args)
{
    ExampleClass ec = new ExampleClass();
    // The following call to exampleMethod1 causes a compiler error
    // if exampleMethod1 has only one parameter. Uncomment the line
    // to see the error.
    //ec.exampleMethod1(10, 4);

    dynamic dynamic_ec = new ExampleClass();
    // The following line is not identified as an error by the
    // compiler, but it causes a run-time exception.
    dynamic_ec.exampleMethod1(10, 4);

    // The following calls also do not cause compiler errors, whether
    // appropriate methods exist or not.
    dynamic_ec.someMethod("some argument", 7, null);
    dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
    public ExampleClass() { }
    public ExampleClass(int v) { }

    public void exampleMethod1(int i) { }

    public void exampleMethod2(string str) { }
}

Роль компилятора в этих примерах заключается в том, чтобы упаковать сведения о том, что каждая инструкция предлагает сделать для dynamic объекта или выражения. Среда выполнения проверяет хранимую информацию и любую инструкцию, которая не является допустимой, вызывает исключение во время выполнения.

Результатом большинства динамических операций является сам dynamic. Например, при наведении указателя мыши на testSum в следующем примере IntelliSense отображает тип (локальная переменная) dynamic testSum.

dynamic d = 1;
var testSum = d + 3;
// Rest the mouse pointer over testSum in the following statement.
System.Console.WriteLine(testSum);

Операции, в которых результат не dynamic включается:

  • Преобразования из dynamic в другой тип.
  • Вызовы конструктора, которые включают аргументы типа dynamic.

Например, testInstance в следующих объявлениях имеет тип ExampleClass, а не dynamic:

var testInstance = new ExampleClass(d);

Преобразования

Преобразования динамических объектов в другие типы выполнять очень просто. Преобразования позволяют разработчику переключаться между динамическим и нединамических поведением.

Вы можете преобразовать любой объект dynamic в неявно, как показано в следующих примерах.

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

И наоборот, можно динамически применять любое неявное преобразование к любому выражению типа dynamic.

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

Разрешение перегрузки с аргументами типа dynamic

Разрешение перегрузки возникают во время выполнения, а не компиляции, если один или несколько аргументов в вызове метода имеют тип dynamic либо получатель вызова метода имеет тип dynamic. В следующем примере, если единственный доступный exampleMethod2 метод принимает строковый аргумент, отправка d1 как аргумент не приводит к ошибке компилятора, но вызывает исключение во время выполнения. Разрешение перегрузки завершается ошибкой во время выполнения, поскольку d1 имеет тип времени выполнения int, а exampleMethod2 требуется строка.

// Valid.
ec.exampleMethod2("a string");

// The following statement does not cause a compiler error, even though ec is not
// dynamic. A run-time exception is raised because the run-time type of d1 is int.
ec.exampleMethod2(d1);
// The following statement does cause a compiler error.
//ec.exampleMethod2(7);

Среда DLR

Среда выполнения динамического языка (DLR) предоставляет инфраструктуру, которая поддерживает dynamic тип в C#, а также реализацию динамических языков программирования, таких как IronPython и IronRuby. Дополнительные сведения о DLR см. в разделе Общие сведения о среде DLR.

взаимодействие COM

Многие методы COM допускают вариативность в типах аргументов и возвращают тип, назначая типы как object. Взаимодействие COM требует явного приведения значений для координации с строго типизированными переменными в C#. При компиляции с использованием параметра EmbedInteropTypes (параметры компилятора C#) введение типа dynamic позволяет обрабатывать вхождения object в сигнатурах COM, как если бы они имели тип dynamic, и таким образом избежать большей части приведения. Дополнительные сведения об использовании dynamic типа с COM-объектами см. в статье о доступе к объектам взаимодействия Office с помощью функций C#.

Заголовок Description
Динамический Описывает применение ключевого слова dynamic.
Общие сведения о среде DLR Содержит общие сведения о среде DLR — среде выполнения, которая добавляет в общую среду языковой среды исполнения (CLR) набор служб для динамических языков.
Пошаговое руководство. Создание и использование динамических объектов Содержит пошаговые инструкции по созданию пользовательских динамических объектов и проекта, который обращается к библиотеке IronPython.