Groupby 1 страница
Выражение запроса вида from x in e group v by k переводится в (e). GroupBy (x => k, x => v) за исключением случая, когда v является идентификатором x, тогда перевод имеет вид (e). GroupBy (x => k) В примере from c in customers переводится в customers. 7.16.2.7 Прозрачные идентификаторы При некоторых переводах вставляются переменные диапазона с прозрачными идентификаторами, обозначенными *. Прозрачные идентификаторы не являются правильным языковым средством, они существуют только в виде промежуточного этапа в процессе перевода выражений запросов. Когда при переводе запроса вставляется прозрачный идентификатор, дальнейшие этапы перевода распространяют прозрачный идентификатор в анонимные функции и анонимные инициализаторы объектов. В таких контекстах прозрачные идентификаторы функционируют следующим образом. · Когда прозрачный идентификатор является параметром анонимной функции, члены связанного анонимного типа автоматически оказываются в области действия в теле анонимной функции. · Когда член с прозрачным идентификатором находится в области действия, члены этого члена также находятся в области действия. · Когда прозрачный идентификатор оказывается в роли декларатора члена в инициализаторе анонимного объекта, он создает член с прозрачным идентификатором. На этапах перевода, описанных выше, прозрачные идентификаторы всегда создаются вместе с анонимными типами с намерением сохранить несколько переменных диапазона в виде членов одного объекта. В реализации C# для группирования нескольких переменных диапазона можно использовать механизм, отличный от анонимных типов. В следующих примерах перевода предполагается использование анонимных типов и показывается, как при переводе можно избавиться от прозрачных идентификаторов. В примере from c in customers переводится в from * in customers. и далее переводится в customers. что после удаления прозрачных идентификаторов эквивалентно customers. где x — идентификатор, созданный компилятором, который в других условиях является невидимым и недоступным. В примере from c in customers переводится в from * in customers. что дальше сокращается до customers. конечный перевод имеет вид customers. где x, y и z — идентификаторы, созданные компилятором, которые в других условиях являются невидимыми и недоступными. 7.16.3 Шаблон выражения запроса Шаблон выражения запроса задает шаблон методов, которые могут реализовываться в типах для поддержки выражений запросов. Поскольку выражения запросов переводятся в вызовы методов с помощью синтаксического сопоставления, в типах можно реализовывать шаблоны выражений запроса с большой гибкостью. Например, методы шаблона можно реализовать в виде методов экземпляра или методов расширения, потому что они имеют одинаковый синтаксис вызова, а методы могут запрашивать делегаты или деревья выражений, потому что анонимные функции можно преобразовывать в оба типа. Ниже представлен рекомендуемый формат универсального типа C<T>, который поддерживает шаблон выражения запроса. Универсальный тип используется, чтобы продемонстрировать правильные отношения между параметрами и результирующими типами, но шаблон также можно реализовать и для неуниверсальных типов. delegate R Func<T1,R>(T1 arg1); delegate R Func<T1,T2,R>(T1 arg1, T2 arg2); class C class C<T>: C public C<U> Select<U>(Func<T,U> selector); public C<V> SelectMany<U,V>(Func<T,C<U>> selector, public C<V> Join<U,K,V>(C<U> inner, Func<T,K> outerKeySelector, public C<V> GroupJoin<U,K,V>(C<U> inner, Func<T,K> outerKeySelector, public O<T> OrderBy<K>(Func<T,K> keySelector); public O<T> OrderByDescending<K>(Func<T,K> keySelector); public C<G<K,T>> GroupBy<K>(Func<T,K> keySelector); public C<G<K,E>> GroupBy<K,E>(Func<T,K> keySelector, class O<T>: C<T> public O<T> ThenByDescending<K>(Func<T,K> keySelector); class G<K,T>: C<T> В методах выше используются универсальные типы делегатов Func<T1, R> и Func<T1, T2, R>, но в них так же успешно можно было бы использовать другие типы делегатов или деревьев выражений с такими же отношениями между типами параметров и результатов. Обратите внимание на рекомендуемое отношение между C<T> и O<T>, которое гарантирует, что методы ThenBy и ThenByDescending будут доступны только для результата операторов OrderBy или OrderByDescending. Также обратите внимание на рекомендуемый формат результата оператора GroupBy — последовательность последовательностей, где каждая внутренняя последовательность имеет дополнительное свойство Key. Пространство имен System.Linq предоставляет реализацию шаблона операторов запроса для любого типа, в котором реализуется интерфейс System.Collections.Generic.IEnumerable<T>. 7.17 Операторы присваивания Операторы присваивания назначают новое значение переменной, свойству, событию или элементу индексатора. присваивание: оператор_присваивания: Левый операнд присваивания должен быть выражением с классом переменной, доступа к свойству, доступа к индексатору или доступа к событию. Оператор = называется простым оператором присваивания. Он присваивает значение правого операнда переменной, свойству или элементу индексатора, который представлен левым операндом. Левый операнд оператора простого присваивания не может быть доступом к событию (за исключением случая, описанного в разделе §10.8.1). Простой оператор присваивания описывается в разделе §7.17.1.
|