Поиск на сайте: Расширенный поиск


Новые программы oszone.net Читать ленту новостей RSS
CheckBootSpeed - это диагностический пакет на основе скриптов PowerShell, создающий отчет о скорости загрузки Windows 7 ...
Вы когда-нибудь хотели создать установочный диск Windows, который бы автоматически установил систему, не задавая вопросо...
Если после установки Windows XP у вас перестала загружаться Windows Vista или Windows 7, вам необходимо восстановить заг...
Программа подготовки документов и ведения учетных и отчетных данных по командировкам. Используются формы, утвержденные п...
Red Button – это мощная утилита для оптимизации и очистки всех актуальных клиентских версий операционной системы Windows...
OSzone.net Microsoft Разработка приложений Языки программирования Применение ключевого слова dynamic в C# 4.0 RSS

Применение ключевого слова dynamic в C# 4.0

Текущий рейтинг: 3.67 (проголосовало 6)
 Посетителей: 3483 | Просмотров: 4688 (сегодня 0)  Шрифт: - +

Введение статической проверки типов было важной вехой в истории языков программирования. В 1970-х в языках вроде Pascal и C появились статическая проверка типов и строгая типизация. Благодаря такой проверке компилятор генерирует ошибку для любого вызова, где предпринимается попытка передачи в метод аргумента с неправильным типом. Аналогичным образом вы получите ошибку компиляции, если попытаетесь вызвать метод, отсутствующий в экземпляре типа.

В других языках был взят противоположный подход — применение динамической проверки типов. Этот подход противоречит идее того, что тип переменной должен быть определен статически в период компиляции и не может меняться, пока данная переменная находится в области видимости. Однако обратите внимание, что динамическая проверка типов вовсе не означает полной свободы в смешивании типов. Например, даже при такой проверке типов вы все равно не сможете добавить булево значение к целому. Вся разница в том, что проверка осуществляется при выполнении программы, а не при ее компиляции.

Статическая типизация или динамическая

Visual Studio 2010 и C# 4.0 поддерживают новое ключевое слово dynamic, которое разрешает динамическую типизацию в языках с традиционной ориентацией на статическую типизацию. Но, прежде чем рассматривать аспекты этого ключевого слова в C# 4.0, нужно договориться о некоторой базовой терминологии.

Давайте определим переменную как хранилище, которое может содержать лишь значения одного конкретного типа. Далее выделим четыре фундаментальных свойства статически типизированного языка:

  • каждое выражение дает тип, известный на этапе компиляции;
  • каждая переменная ограничена типом, известным на этапе компиляции;
  • компилятор гарантирует, что ограничения типов в выражениях, присваиваемых переменным, соответствуют ограничениям переменных;
  • задачи семантического анализа наподобие разрешения перегруженных версий выполняются при компиляции, а результаты помещаются в сборку.

Динамический язык имеет обратные качества. Не у каждого выражения на этапе компиляции известен тип результата; то же самое относится к переменным. Ограничения хранилища, если они вообще есть, проверяются в период выполнения и игнорируются при компиляции. Семантический анализ происходит только в период выполнения.

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

Однако, что касается соответствующих атрибутов вроде dynamic и static (или, возможно, strong и weak), то на сегодняшний день их лучше применять к индивидуальным языковым средствам, чем к языку в целом.

Возьмем, например, Python и PHP. Оба языка динамические, позволяют использовать переменные и разрешают исполняющей среде вычислять их реальные типы. Но в PHP есть возможность хранения, скажем, целых значений и строк в одной переменной в той же области видимости. В этом отношении PHP (подобно JavaScript) является слабо типизированным динамическим языком.

С другой стороны, Python дает лишь один шанс задать тип переменной, что делает его более строго типизированным. Вы можете присваивать тип переменной динамически и позволить исполняющей среде логически определять его, исходя из присвоенного значения. Однако после этого вам не будет дозволено записывать в эту переменную какое-либо значение неподходящего типа.

Динамические типы в C#

В C# 4.0 есть средства, которые являются одновременно динамическими и статическими, а также слабо и строго типизированными. Хотя C# зарождался как статически типизированный язык, он стал динамически типизированным в любом контексте, где вы можете использовать ключевое слово dynamic, например:

   

dynamic number = 10;
Console.WriteLine(number);

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

Заметьте, что C# 4.0 не заставляет вас использовать dynamic — точно так же, как C# 3.0 не вынуждал применять var, лямбды или инициализаторы объектов. C# 4.0 предоставляет новое ключевое слово dynamic специально, чтобы облегчить обработку общеизвестных случаев. Сам язык остается в основной части статически типизированным, хотя в него добавлена возможность более эффективного взаимодействия с динамическими объектами.

Зачем может понадобиться динамический объект? Во-первых, вы можете не знать тип объекта, с которым вам приходится иметь дело. Какие-то намеки у вас могут быть, но этого недостаточно для статического присваивания определенного типа данной переменной — как раз такое и случается во многих распространенных случаях, например при работе с COM-объектами или использовании отражения для получения экземпляров. В этом контексте ключевое слово dynamic снимает часть головной боли в подобных ситуациях. Код, написанный с использованием dynamic, легче читать и писать, а значит, и само приложение будет проще в понимании и сопровождении.

Во-вторых, вашему объекту может быть присуща изменчивая природа. Вы можете работать с объектами, созданными в средах динамического программирования, таких как IronPython и IronRuby. Но вы также можете задействовать эту функциональность для объектов HTML DOM (свойств expando) и Microsoft .NET Framework 4, которые изначально проектировались как динамические.

Использование dynamic

Важно понимать, что dynamic в системе типов C# является типом. У него очень специфический смысл, но это именно тип, и поэтому его нужно обрабатывать как таковой. Вы можете указать dynamic в качестве типа объявляемой вами переменной, типа элементов в наборе или возвращаемого значения метода. Кроме того, dynamic можно применять как тип параметра метода. Но использовать dynamic с оператором typeof или в качестве базового типа класса нельзя.

Следующий код показывает, как объявить динамическую переменную в теле метода:

   

public void Execute()  {
  dynamic calc = GetCalculator();
  int result = calc.Sum(1, 1);
}

Если вы достаточно знаете о типе объекта, возвращаемого методом GetCalculator, то можете объявить переменную calc соответствующего типа или как var, переложив на компилятор все детали. Но применение var или явного статического типа потребовало бы от вас полной уверенности в том, что в контракте, предоставляемом типом, который возвращается GetCalculator, существует метод Sum. Если такого метода нет, вы получите ошибку компиляции.

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

Это ключевое слово применимо и к свойству класса. При этом вы можете дополнить этот член любым модификатором видимости — public, protected и даже static.

Гибкость ключевого слова dynamic показана на рис. 1. В основной программе у меня есть динамическая переменная, экземпляр которой создается на основе значения, возвращаемого из вызванной функции. От этого не было бы особого толку, если бы не тот факт, что функция принимает и возвращает динамический объект. Интересно посмотреть, что происходит, когда вы, например, передаете число, а затем пытаетесь его удвоить в функции.

Рис. 1. Использование dynamic в сигнатуре как функции

   

class Program {
  static void Main(string[] args) {
    // The dynamic variable gets the return
    // value of a function call and outputs it.
    dynamic x = DoubleIt(2);
    Console.WriteLine(x);

    // Stop and wait
    Console.WriteLine(“Press any key”);
    Console.ReadLine();
  }

  // The function receives and returns a dynamic object
  private static dynamic DoubleIt(dynamic p) {
    // Attempt to "double" the argument whatever
    // that happens to produce

    return p + p;
  }
}

Если вы передадите в функцию число 2, получите значение 4. А если вы передадите 2 как строку, получите 22. Внутри функции оператор + разрешается динамически, исходя из типа операндов в период выполнения. Если вы смените тип на System.Object, то получите ошибку компиляции, так как оператор + не определен в System.Object. Ключевое слово dynamic поддерживает случаи, которые были бы невозможны без него.

Dynamic и System.Object

До .NET Framework 4 сделать так, чтобы метод возвращал разные типы в зависимости от условий, можно было только с помощью общего базового класса. Вероятно, вы решали эту задачу, прибегая к System.Object. Функция, возвращающая System.Object, делает доступным вызвавшему коду экземпляр, который можно привести почти к любому типу. Так чем же использование dynamic лучше System.Object?

В C# 4.0 реальный тип переменной, объявленной как dynamic, разрешается в период выполнения, а компилятор просто полагает, что объект в динамической переменной поддерживает любые операции. То есть вы можете написать код, который вызывает метод объекта, который, как вы ожидаете, появится в ней в период выполнения:

   

dynamic p = GetSomeReturnValue();
p.DoSomething();

В C# 4.0 компилятор не станет жаловаться на этот код. Аналогичный код с использованием System.Object, не пройдет компиляцию и потребует для работы некоторых ухищрений с вашей стороны — отражения или авантюрного приведения типов.

Ключевые слова var и dynamic

Эти ключевые слова лишь кажутся похожими. Var указывает тип переменной, который должен быть присвоен типу инициализатора периода компиляции.

Но dynamic подразумевает, что тип переменной является динамическим, поддерживаемым в C# 4.0. В конечном счете dynamic и var имеют совершенно разный смысл. Var улучшает статическую типизацию. Это ключевое слово помогает компилятору корректно распознать тип переменной по точному типу, возвращаемому инициализатором.

Ключевое слово dynamic обеспечивает полный уход от статической типизации. При использовании в объявлении переменной оно указывает компилятору вообще не обрабатывать тип переменной. Тип должен быть таким, каким он окажется в период выполнения. В случае var ваш код статически типизируется — так же, как если бы вы выбрали классический подход с применением явных типов в объявлении переменной.

Другое различие между этими двумя ключевыми словами состоит в том, что var может появляться только в объявлении локальной переменной. Использовать var для определения свойства класса, возвращаемого значения или параметра функции нельзя.

Как разработчик вы можете применять dynamic с переменными, которые могут содержать объекты неопределенного типа, например объекты, возвращаемые COM или DOM API, получаемые от динамических языков (скажем, IronRuby), через механизм отражения или от объектов, динамически встраиваемых в C# 4.0 с использованием новых средств расширения.

Но динамический тип не обходит проверки типов. Он лишь отодвигает их на период выполнения. Если в период выполнения будут обнаружены несовместимости по типам, вы получите исключения.

Автор: Дино Эспозито  •  Иcточник: Журнал MSDN  •  Опубликована: 26.01.2011
Нашли ошибку в тексте? Сообщите о ней автору: выделите мышкой и нажмите CTRL + ENTER
Теги:  


Оценить статью:
Вверх
Комментарии посетителей
Комментарии отключены. С вопросами по статьям обращайтесь в форум.