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

7.6.5.2Вызовы методов расширения

Для вызова метода (§7.5.5.1) одного из видов

выражение . идентификатор ( )

выражение . идентификатор ( args )

выражение . идентификатор < typeargs > ( )

выражение . идентификатор < typeargs > ( args )

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

Задачей является найти лучшее имя_типа C, чтобы можно было вызвать соответствующий статический метод:

C . идентификатор ( выражение )

C . идентификатор ( выражение , args )

C . идентификатор < typeargs > ( выражение )

C . идентификатор < typeargs > ( выражение , args )

Метод расширения Ci.Mj доступен, если:

  • Ci не является универсальным или вложенным классом

  • Mj имеет имя идентификатор

  • Mj доступен и применим для аргументов как статический метод, как указано выше

  • От выражения до типа первого параметра Mj существует неявная идентификация, ссылка или преобразование упаковки.

Поиск C выполняется следующим образом.

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

  • Если данное пространство имен или блок компиляции напрямую содержит объявления неуниверсального типа Ci с доступными методами расширения Mj, то набор этих методов является набором кандидатов.

  • Если пространства имен, импортированные с помощью директив пространства имен в данном пространстве имен или блоке компиляции, напрямую содержат объявления неуниверсального типа Ci с доступными методами расширения Mj, то набор этих методов является набором кандидатов.

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

  • Иначе к набору кандидатов применяется разрешение перегрузки, как описано в разделе (§7.5.3). Если один лучший метод не найден, то возникает ошибка времени компиляции.

  • C — это тип, в котором лучший метод объявляется в качестве метода расширения.

После этого с помощью C выполняется вызов метода в виде вызова статического метода (§7.5.4).

Указанные выше правила означают, что методы экземпляра имеют приоритет по сравнению с методами расширения, что методы расширения, доступные во внутренних объявлениях пространств имен, имеют приоритет по сравнению с методами расширения, доступными во внешних объявлениях пространств имен, и что методы расширения, объявленные непосредственно в пространстве имен, имеют приоритет над методами расширения, импортированными в это же пространство имен с помощью директивы пространства имен. Например:

public static class E { public static void F(this object obj, int i) { }

public static void F(this object obj, string s) { } }

class A { }

class B { public void F(int i) { } }

class C { public void F(object obj) { } }

class X { static void Test(A a, B b, C c) { a.F(1); // E.F(object, int) a.F("hello"); // E.F(object, string)

b.F(1); // B.F(int) b.F("hello"); // E.F(object, string)

c.F(1); // C.F(object) c.F("hello"); // C.F(object) } }

В этом примере метод B имеет приоритет по сравнению с первым методом расширения, а метод C имеет приоритет над обоими методами расширения.

public static class C { public static void F(this int i) { Console.WriteLine("C.F({0})", i); } public static void G(this int i) { Console.WriteLine("C.G({0})", i); } public static void H(this int i) { Console.WriteLine("C.H({0})", i); } }

namespace N1 { public static class D { public static void F(this int i) { Console.WriteLine("D.F({0})", i); } public static void G(this int i) { Console.WriteLine("D.G({0})", i); } } }

namespace N2 { using N1;

public static class E { public static void F(this int i) { Console.WriteLine("E.F({0})", i); } }

class Test { static void Main(string[] args) { 1.F(); 2.G(); 3.H(); } } }

Вывод в данном примере имеет вид:

E.F(1) D.G(2) C.H(3)

D.G имеет приоритет над C.G, а E.F имеет приоритет над D.F и C.F.

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