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

7.5.2.11Фиксирование

Нефиксированная переменная типа Xi с набором границ фиксируется следующим образом.

  • Набор типов кандидатов Uj изначально формируется как набор всех типов в наборе границ для Xi.

  • Затем по очереди проверяется каждая граница для Xi: Для каждой границы U для Xi все типы Uj, не являющиеся идентичными U, удаляются из набора кандидатов. Для каждой нижней границы U для Xi из набора кандидатов удаляются все типы Uj, в которые не существует неявного преобразования из U. Для каждой верхней границы U для Xi из набора кандидатов удаляются все типы Uj, в которые не существует неявного преобразования из U.

  • Если среди оставшихся типов-кандидатов Uj имеется уникальный тип V, из которого существует неявное преобразование во все остальные типы-кандидаты, то Xi фиксируется в V.

  • Иначе вывод типа завершается сбоем.

7.5.2.12Выведенный тип возвращаемого значения

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

  • Если телом F является выражение, то выведенный тип возвращаемого значения F совпадет с типом этого выражения.

  • Если телом F является блок, а самым подходящим общим типом для набора выражений в операторах return блока является T (§7.5.2.14), то выведенным типом возвращаемого значения F будет T.

  • Иначе тип возвращаемого значения для E вывести нельзя.

В качестве примера вывода типа с анонимной функцией рассмотрим метод расширения Select, объявленный в классе System.Linq.Enumerable:

namespace System.Linq { public static class Enumerable { public static IEnumerable<TResult> Select<TSource,TResult>( this IEnumerable<TSource> source, Func<TSource,TResult> selector) { foreach (TSource element in source) yield return selector(element); } } }

Предположим, что пространство имен System.Linq было импортировано с помощью предложения using и у класса Customer свойство Name имеет тип string. Тогда для выбора имен списка клиентов можно использовать метод Select:

List<Customer> customers = GetCustomerList(); IEnumerable<string> names = customers.Select(c => c.Name);

Вызов метода расширения (§7.6.5.2) для Select обрабатывается путем перезаписи вызова статического метода:

IEnumerable<string> names = Enumerable.Select(customers, c => c.Name);

Поскольку аргументы типа не были указаны явно, для получения аргументов типа используется вывод типа. Сначала аргумент customers связывается с параметром source, и для T выводится тип Customer. Затем с помощью описанного выше процесса вывода типа анонимной функции c присваивается тип Customer, а выражение c.Name связывается с типом возвращаемого значения параметра selector, и для S выводится тип string. Таким образом, этот вызов эквивалентен

Sequence.Select<Customer,string>(customers, (Customer c) => c.Name)

а результат имеет тип IEnumerable<string>.

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

static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) { return f2(f1(value)); }

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

double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);

продолжается следующим образом: сначала аргумент «1:15:30» связывается с параметром value, и для X выводится тип string. Затем параметру первой анонимной функции s присваивается выведенный тип string, а выражение TimeSpan.Parse(s) связывается с типом возвращаемого значения f1, и для Y выводится тип System.TimeSpan. Наконец, параметр второй анонимной функции t получает выведенный тип System.TimeSpan, а выражение t.TotalSeconds связывается с типом возвращаемого значения f2, и для Z выводится тип double. Таким образом, результат вызова имеет тип double.

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