Динамическое заражение, часть первая

 

Предположим, что вы эпидемиолог, моделирующий возможное распространение сильно заразной болезни. Прямой способ моделирования серии прискорбных событий – предположить, что население может быть разделено на три категории: определенно зараженных, определенно здоровых и возможно зараженных. Если здоровый встречается с зараженным или возможно зараженным, то он переходит в категорию возможно зараженных. (Или, иначе, категория возможно зараженных транзитивно замкнута относительно отношения заражения.) Член категории возможно зараженных становится либо определенно здоровым, либо определенно зараженным после некоторых тестов. И зараженный может стать здоровым, пройдя лечение.

Такой вид модели заражения довольно распространен при конструировании вычислительных систем. Например, предположим, что у вас есть веб-сайт, принимающий строки от пользователя, сохраняющий их в базе данных и подсовывающий их другим пользователям. Например, этот блог, который собирает комментарии от вас, сохраняет их в базе данных и затем подсовывает обратно другим пользователям. Это атака носит название Cross Site Scripting (XSS) и может случиться прямо здесь. Общий способ смягчения XSS-проблемы состоит в изменении данных, использующих модель заражения для выявления возможно злокачественных строк. Что бы вы ни делали с потенциально злокачественными строками, например, соединяли их с доброкачественными строками, результатом будет возможно злокачественная строка. Если строка с помощью некоторого теста определяется как доброкачественная, или из нее вырезаются потенциально злокачественные части, то она становится безопасной.

Возможность применения оператора «dynamic» в С# 4 и более старших версиях имеет много общего с таким типом заражения. Как я отметил в прошлый раз, когда аргумент вызова динамическая переменная, то довольно велики шансы, что компилятор определит, что результат вызова также является динамическим; зараза распространяется. Фактически, при использовании почти любого оператора в динамическом выражении, результат будет динамическим за несколькими исключениями (например, оператор «is» всегда возвращает булевский тип результата). Можно «вылечить» выражение, чтобы предотвратить распространение динамизма, отбрасывая его к типу object, или к какому-то другому не динамическому типу по вашему выбору; отбрасывание динамического типа к объекту – это изменение его идентичности.

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