Break, continue и goto 23 страница
7.4.2.6 Вывод типа вывода; Вывод типа вывода выполняется из выражения E с типом T следующим образом: · Если E является анонимной функцией с полученным типом возвращаемого значения U (§7.4.2.11), а T является типом делегата или типом дерева выражения с типом возвращаемого значения Tb, то выполняется вывод из U для Tb по нижней границе (§7.4.2.9). · Иначе, если E является группой методов, а T является типом делегата или типом возвращаемого значения дерева выражения Tb с типами параметров T1…Tk и типом возвращаемого значения Tb, и разрешение перегрузки E с типами T1…Tk дает один метод с типом возвращаемого значения U, то выполняется вывод из U для Tb по нижней границе. · Иначе, если e является выражением с типом U, то выполняется вывод из U для T по нижней границе. · Иначе вывод не производится. 7.4.2.7 Вывод явных типов параметров Вывод явных типов параметров выполняется из выражения E с типом T следующим образом. Если E является анонимной функцией c явным указанием типа с типами параметров U1…Uk и T является типом делегата с типами параметров V1…Vk, то для каждого типа Ui выполняется точный вывод (§7.4.2.8) из Ui для соответствующего Vi. 7.4.2.8 Точный вывод; Точный вывод из типа U для типа V выполняется следующим образом. · Если V является одним из нефиксированных Xi, то U добавляется к набору границ для Xi. · Иначе, если U является типом массива Ue[…] и V является типом массива Ve[…] одного ранга, выполняется точный вывод из Ue в Ve. · Иначе, если V является сформированным типом C<V1…Vk> и U является сформированным типом C<U1…Uk>, то выполняется точный вывод из каждого типа Ui в соответствующий Vi. · Иначе вывод не производится. 7.4.2.9 Вывод нижних границ; Вывод нижних границ из типа U для типа V выполняется следующим образом. · Если V является одним из нефиксированных Xi, то U добавляется к набору границ для Xi. · Иначе, если U является типом массива Ue[…] и V является типом массива Ve[…] такого же ранга, либо если U является типом одномерного массива Ue[]и V является одним из интерфейсов IEnumerable<Ve>, ICollection<Ve> или IList<Ve>, то o если известно, что Ue является ссылочным типом, то выполняется вывод из Ue в Ve по нижней границе; o иначе выполняется точный вывод из Ue в Ve. · Иначе, если V является сформированным типом C<V1…Vk> и имеется уникальный набор типов U1…Uk, такой что существует стандартное неявное преобразование из U в C<U1…Uk>, выполняется точный вывод из каждого Ui для соответствующего Vi. · Иначе вывод не производится. 7.4.2.10 Фиксирование; Нефиксированная переменная типа Xi с набором границ фиксируется следующим образом. · Набор типов кандидатов; Uj изначально формируется как набор всех типов в наборе границ для Xi. · Затем по очереди проверяется каждая граница для Xi: для каждой границы U для Xi из набора кандидатов удаляются все типы Uj, в которые не; существует стандартного неявного преобразования из U. · Если среди оставшихся типов-кандидатов Uj имеется уникальный тип V, из которого существует стандартное неявное преобразование во все остальные типы-кандидаты, то Xi фиксируется в V. · Иначе вывод типа завершается сбоем. 7.4.2.11 Выведенный тип возвращаемого значения Выведенный тип возвращаемого значения анонимной функции F используется при выводе типа и разрешении перегрузки. Выведенный тип возвращаемого значения можно определить только для анонимной функции со всеми известными типами параметров, которые либо заданы явно и переданы через преобразование анонимной функции, либо выведены во время вывода типа для включающего вызова универсального метода. Выведенный тип возвращаемого значения определяется следующим образом. · Если телом F является выражение, то выведенный тип возвращаемого значения F совпадет с типом этого выражения. · Если телом F является блок, а самым подходящим общим типом для набора выражений в операторах return блока является T (§7.4.2.13), то выведенным типом возвращаемого значения F будет T. · Иначе тип возвращаемого значения для E вывести нельзя. В качестве примера вывода типа с анонимной функцией рассмотрим метод расширения Select, объявленный в классе System.Linq.Enumerable: namespace System.Linq Предположим, что пространство имен System.Linq было импортировано с помощью предложения using и у класса Customer свойство Name имеет тип string. Тогда для выбора имен списка клиентов можно использовать метод Select: List<Customer> customers = GetCustomerList(); Вызов метода расширения (§7.5.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) { вывод типа при вызове 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.
|