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


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

Тип 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.
// Uncomment the line to see the error.
// ec.exampleMethod2(7);

Среда выполнения динамических языков (DLR)

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

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

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

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