Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

6.6Преобразования группы методов

Существует неявное преобразование (§6.1) из группы методов (§7.1) к совместимому типу делегата. Для типа делегата D и выражения E, которое классифицируется как группа методов, неявное преобразование из E к D существует в том случае, если E содержит как минимум один метод, который применим в нормальной форме (§7.5.3.1) к списку аргументов, созданному с использованием типов параметров и модификаторов типа D, как описано далее.

Применение во время компиляции преобразования из группы методов E к типу делегата D описывается далее. Обратите внимание, что существование неявного преобразования из E к D не гарантирует, что его выполнение во время компиляции будет завершено без ошибок.

  • Отдельный метод M выбирается соответствующим вызову метода (§7.6.5.1) в форме E(A) со следующими модификациями:

  • Список аргументов A представляет собой список выражений, которые классифицируются как переменные с типом и модификатором (ref или out), соответствующими параметрам в списке_формальных_параметров типа D.

  • Допустимыми считаются только те методы, которые применимы в нормальной форме (§7.5.3.1), а не те, которые применимы только в расширенной форме.

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

  • Выбранный метод M должен быть совместим (§15.2) с типом делегата D. В противном случае порождается ошибка времени компиляции.

  • Если выбранный метод M является методом экземпляра, выражение экземпляра, связанное с E, определяет конечный объект делегата.

  • Если выбранный метод M является методом расширения, который определяется посредством обращения к члену выражения экземпляра, такое выражение определяет конечный объект делегата.

  • Результатом преобразования является значение типа D, то есть вновь созданный делегат, который ссылается на выбранный метод и конечный объект.

Обратите внимание, что в результате этого процесса может быть создан делегат метода расширения. Это происходит в том случае, если алгоритм §7.6.5.1 не находит метод экземпляра, однако успешно выполняет вызов E(A) в качестве вызова метода расширения (§7.6.5.2). Созданный таким образом делегат записывает метод расширения и его первый аргумент.

Далее приведен пример преобразования группы методов:

delegate string D1(object o);

delegate object D2(string s);

delegate object D3();

delegate string D4(object o, params object[] a);

delegate string D5(int i);

class Test { static string F(object o) {...}

static void G() { D1 d1 = F; // Ok D2 d2 = F; // Ok D3 d3 = F; // Error – not applicable D4 d4 = F; // Error – not applicable in normal form D5 d5 = F; // Error – applicable but not compatible

} }

При присваивании d1 выполняется неявное преобразование группы методов F к значению типа D1.

Операция присваивания d2 демонстрирует возможность создания делегата для метода, который обладает производными типами параметра более низкого уровня (контравариантными) и производным типом возвращаемого значения более высокого уровня (ковариантным).

Операция присваивания d3 демонстрирует отсутствие преобразования в случае неприменимости метода.

Операция присваивания d4 демонстрирует, как необходимо применять метод в нормальной форме.

Операция присваивания d5 демонстрирует, что применение различного типа параметров и возвращаемых значений делегата и метода допустимо только для ссылочных типов.

Как и для любых других явных и неявных преобразований, для явного выполнения преобразования группы методов можно использовать оператор приведения. Таким образом, в примере

object obj = new EventHandler(myDialog.OkClick);

может быть записан как

object obj = (EventHandler)myDialog.OkClick;

Группы методов могут влиять на разрешение перегрузки, а также использоваться при определении типа. Дополнительные сведения см. в §7.5.

Вычисление преобразования группы методов во время выполнения осуществляется в следующем порядке:

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

  • Выполняется вычисление выражения экземпляра. Если при этом вычислении возникает исключение, дальнейшие этапы не выполняются.

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

  • Если выражение экземпляра имеет тип_значений, выполняется операция упаковки (§4.3.1) для преобразования значения к объекту. Этот объект становится конечным объектом.

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

  • Создается новый экземпляр типа делегата D. Если для создания нового экземпляра недостаточно памяти, то возникает исключение System.OutOfMemoryException и дальнейшие этапы не выполняются.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]