Re[28]: Аллокации
От: vdimas Россия  
Дата: 09.07.18 12:50
Оценка:
Здравствуйте, Qbit86, Вы писали:

S>>А можно узнать, у нутре линка не так? И как должно быть так?

Q>Linq сформулирован в терминах IEnumerable<T>/IEnumerator<T> вместо constrained TEnumerable/TEnumerator

+1
Хотя ничто не мешало реализовать весь набор функциональности параллельно — оно бы не мешало друг другу.

Еще момент: когда тела выражений переводятся в ExpressionTree (IQueryable) — это понятно, для того и затевалось, но когда тупо в делегаты (для IEnumerable<>) при том, что локальные зависимости хоролшо отличимы от внешних — это совсем уж жесть, ИМХО. Множит всю затею на ноль. Весь этот код можно было бы тупо инлайнить.
Re[29]: Аллокации
От: Qbit86 Кипр
Дата: 09.07.18 13:03
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Хотя ничто не мешало реализовать весь набор функциональности параллельно — оно бы не мешало друг другу.


Мешало бы тем, что было бы очень тяжеловесно для использования. Интерфейсы стирают типы, тем упрощают сигнатуры. Иначе вместо интерфейса IEnumerable<T> с одним типовым параметром нужен был бы констрейнт IEnumerable<T, TEnumerator> where TEnumerator : IEnumerator<T>, и все три типовых параметра <T, TEnumerable, TEnumerator> нужно было бы протаскивать во всех сигнатурах.
Глаза у меня добрые, но рубашка — смирительная!
Re[26]: 2D-Linq и оптимизация цифровых фильтров - 3
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.07.18 13:21
Оценка: -1
Здравствуйте, vdimas, Вы писали:


I>>Почему у Синклера вышло вдвое быстрее ?


V>Потому что он вешает вам лапшу на уши, мухлюет — вместо сравнивания быстродействия линка начал со сравнения скорости работы одномерного дотнетного массива vs двумерного, но подал это так, что дело якобы в линке.


Специально перечитал посты Синклера. Идея сравнения скорости двумерного массива с одномерным — не его. Автор — vdimas. Причем здесь Синклер?
Re[30]: Аллокации
От: vdimas Россия  
Дата: 09.07.18 13:27
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>вместо интерфейса IEnumerable<T> с одним типовым параметром нужен был бы констрейнт IEnumerable<T, TEnumerator> where TEnumerator : IEnumerator<T>


Хоть кто-то здраво мыслит! ))

В моих собственных либах дотнета, где у меня практически везде используется value-type, и где всё расписано на подобных ограничениях, я пришёл к подобной технике уже давно. А как только using перестал требовать IDisposable и более не делает структурам боксинг при using — вообще начался кайф. ))

По факту работы с такой техникой никаких особых проблем не выявилось — оно живёт себе в параллель основной "ветке" IEnumerable:
IEnumerable<T, TEnumerator> : IEnumerable<T> 
where TEnumerator : IEnumerator<T> 
{
    TEnumerator GetEnumerator();
}


Т.е. при отсутствии методов-раширений, ожидающих IEnumerable<T, TEnumerator>, подхватываются сигнатуры поверх IEnumerable<T>.
Тут в точности происходит то же самое, что происходило с либами при добавлении IEnumerable<T> : IEnumerabe — примерно такое же соотношение интерфейсов.

Всё вместе представляет из себя что-то вроде той самой "правильной" оптимизации, которая не должна быть premature, а вполне может быть применена точечно, уже после того, как целевые алгоритмы будут отлажены.

============
Насчёт "тяжеловесности" — ХЗ.
При моём агрессивном применение value type другого выхода, кроме как обкладывать всё ограничениями, и нет, бо структуры не наследуются и не могут выступать ограничениями. Поэтому, "наследование" тут происходит чере методы-расширения и новые возможости this in SomeStruct или this ref SomeStruct.

Ну и при конечной целевой компиляции в нейтив вся эта тяжеловесность метаинформации стирается, поэтому париться тут не о чем совершенно.
Re[28]: Аллокации
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.07.18 13:31
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, Sharov, Вы писали:


S>>А можно узнать, у нутре линка не так? И как должно быть так?


Q>Linq сформулирован в терминах IEnumerable<T>/IEnumerator<T> вместо constrained TEnumerable/TEnumerator, в то время как приличные Enumerator'ы — значимые типы (вопреки стандартным рекомендациям про изменяемые структуры). Это приводит к боксингу, и в performance critical коде не рекомендуется:


Linq сформулирован в терминах query expression pattern, который привязан к определенным правилам трансляции над генерик типом C<T>. Никакой привязки к IEnumerable<T> у него нет. Достаточно вспомнить IQueryable и т.п.
И да, действительно там нет constrained TEnumerable/TEnumerator, вместо этого рекомендованная форма C<T>. Что вполне позволяет избегать боксинга.
Re[27]: 2D-Linq и оптимизация цифровых фильтров - 3
От: IB Австрия http://rsdn.ru
Дата: 09.07.18 14:33
Оценка: 16 (2) +1 -1 :)
Здравствуйте, samius, Вы писали:

S>Специально перечитал посты Синклера. Идея сравнения скорости двумерного массива с одномерным — не его. Автор — vdimas. Причем здесь Синклер?

Ну, просто у vdimas очень тонкая душевная организация. Ему оказывается тон сообщения Антона не понравился, вот и рвануло )
А когда рвануло, то все средства хороши — можно и не ту задачу не правильно решить, а потом наехать на оппонента, чтобы все поняли кто виноват...
А можно и вычитать чего не было, блестяще опровергнуть, а потом поливать грязью окружающих, что мол не догнали его гениальную идею. =)
Мы уже победили, просто это еще не так заметно...
Re[26]: 2D-Linq и оптимизация цифровых фильтров - 3
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.07.18 14:49
Оценка: +1 :)
Здравствуйте, vdimas, Вы писали:

I>> Вот такой вот миф Синклер и развенчивает.


V>Давай дождёмся когда развенчает. ))


Уже. Вдвое ускорил, это мало ?

V>>>Никакого мифа нет.

I>>Ты вот утверждаешь, что реальность такая, то есть, что линк тупит и морозит из за рефлексии.
V>Это ты утверждаешь, что именно из-за рефлексии.

Про рефлексию ты выразил согласие "Так и есть, это объективная реальность."
Хорошо бы узнать подробности, а многие говорили про рефлексию и никто так и не смог показать

V>Линк тормозит из-за большого комплекса причин, львиная доля которых к линку не имеет никакого отношения, а просто является св-вами самой платформы.

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

Та ты определись, рефлексия или нет. А то вот по замерам что выкладывали в форуме, получается, что linq2db работает быстрее Dapper, который безо всякого Линка и даже почти как ADO.NET Работает, а при некоторых условиях может и быстрее сыграть.

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


Это общие слова.

I>>Почему у Синклера вышло вдвое быстрее ?


V>Потому что он вешает вам лапшу на уши, мухлюет — вместо сравнивания быстродействия линка начал со сравнения скорости работы одномерного дотнетного массива vs двумерного, но подал это так, что дело якобы в линке.


Он показывает, как разделить код при помощи линка и выиграть на перформансе.
Re[29]: Аллокации
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.07.18 15:08
Оценка:
Здравствуйте, samius, Вы писали:

Q>>Linq сформулирован в терминах IEnumerable<T>/IEnumerator<T> вместо constrained TEnumerable/TEnumerator, в то время как приличные Enumerator'ы — значимые типы (вопреки стандартным рекомендациям про изменяемые структуры). Это приводит к боксингу, и в performance critical коде не рекомендуется:


S>Linq сформулирован в терминах query expression pattern, который привязан к определенным правилам трансляции над генерик типом C<T>. Никакой привязки к IEnumerable<T> у него нет. Достаточно вспомнить IQueryable и т.п.

S>И да, действительно там нет constrained TEnumerable/TEnumerator, вместо этого рекомендованная форма C<T>. Что вполне позволяет избегать боксинга.

Расскажи лучше, из за чего Linq тормозит. А то vdimas, alex_public и многие другие уверены, что из-за рефлексии, но не могут ни показать, не доказать
Re[29]: Аллокации
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.07.18 15:35
Оценка:
Здравствуйте, samius, Вы писали:

Q>>Linq сформулирован в терминах IEnumerable<T>/IEnumerator<T> вместо constrained TEnumerable/TEnumerator, в то время как приличные Enumerator'ы — значимые типы (вопреки стандартным рекомендациям про изменяемые структуры). Это приводит к боксингу, и в performance critical коде не рекомендуется:


S>Linq сформулирован в терминах query expression pattern, который привязан к определенным правилам трансляции над генерик типом C<T>. Никакой привязки к IEnumerable<T> у него нет. Достаточно вспомнить IQueryable и т.п.

S>И да, действительно там нет constrained TEnumerable/TEnumerator, вместо этого рекомендованная форма C<T>. Что вполне позволяет избегать боксинга.

Это query comprehension так сформулирован. А вот Linq уже привязан к конкретным типам, т.к. linq это уже конкретная реализация. IEnumerable — это одна реализация, IQueryable — другая.
Re[30]: Аллокации
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.07.18 16:34
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Здравствуйте, samius, Вы писали:


S>>И да, действительно там нет constrained TEnumerable/TEnumerator, вместо этого рекомендованная форма C<T>. Что вполне позволяет избегать боксинга.


I>Расскажи лучше, из за чего Linq тормозит. А то vdimas, alex_public и многие другие уверены, что из-за рефлексии, но не могут ни показать, не доказать

Расскажи, в каком конкретно случае и с чем именно сравниваем. А то мне за весь Linq как-то сложно отдуваться.
Re[30]: Аллокации
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.07.18 16:43
Оценка: +1
Здравствуйте, Ikemefula, Вы писали:

I>Здравствуйте, samius, Вы писали:


S>>И да, действительно там нет constrained TEnumerable/TEnumerator, вместо этого рекомендованная форма C<T>. Что вполне позволяет избегать боксинга.


I>Это query comprehension так сформулирован. А вот Linq уже привязан к конкретным типам, т.к. linq это уже конкретная реализация. IEnumerable — это одна реализация, IQueryable — другая.


Linq — это технология интеграции запросов в язык. Она привязана к C<T> в спецификации. Linq to Objects — это одна конкретная реализация. Linq to SQL — еще одна. Общего между этими реализациями ничего нет кроме того, что они удовлетворяют правилам трансляции запросов.

Проведем мысленный эксперимент: уберем правило трансляции запросов — запросы остаются, интеграции в язык больше нет. Что общего между реализациями? Ничего. Осталось выяснить, что же тормозит.
Re[27]: 2D-Linq и оптимизация цифровых фильтров - 3
От: vdimas Россия  
Дата: 09.07.18 17:04
Оценка:
Здравствуйте, Ikemefula, Вы писали:

V>>Давай дождёмся когда развенчает. ))

I>Уже. Вдвое ускорил, это мало ?

Задачу зато не решил.
Я не могу взять произвольный алгоритм из этого же класса и воспользоваться его "наработками".
А вот своими наработками — смогу.
В итоге, у Синклера вышла лишь некая забава без полезного выхлопа.
А значит, возвращаемся к началу начал, — все расклады про тормознутость линка остаются в силе.


I>Про рефлексию ты выразил согласие "Так и есть, это объективная реальность."


Там было не только про рефлексию, но мне лень обсуждать с тобой разницу происходящего в случае IEnumerable vs IQueryable.
Кто в курсе, тому те слова были понятны.
А кто не в курсе, тот мается ерундой, гоняясь на форуме за словами, смысла которых не понимает.


I>Хорошо бы узнать подробности, а многие говорили про рефлексию и никто так и не смог показать


Я только что обозначил куда копать.


I>Та ты определись, рефлексия или нет.


Узнаю старика Крупского. ))
Ничего не меняется с годами.
RTFM!


I>А то вот по замерам что выкладывали в форуме, получается, что linq2db работает быстрее Dapper, который безо всякого Линка и даже почти как ADO.NET Работает, а при некоторых условиях может и быстрее сыграть.


Линк большой и разный.
Мы тут зацепились за небольшую часть его.


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

I>Это общие слова.

Спрашивай конкретней — отвечу конкретней.
Но чтобы спросить конкретней, тебе придётся копнуть, бо пока ты даже не понимаешь, что ты хочешь спросить.
Про моё отношение к такому подходу ты в курсе, я уверен. ))


I>>>Почему у Синклера вышло вдвое быстрее ?

V>>Потому что он вешает вам лапшу на уши, мухлюет — вместо сравнивания быстродействия линка начал со сравнения скорости работы одномерного дотнетного массива vs двумерного, но подал это так, что дело якобы в линке.
I>Он показывает, как разделить код при помощи линка и выиграть на перформансе.

Было бы решение целиком на виду, я бы тебе показал, как добиться того же самого без IL-асма и прочих танцев с бубном.

Фишка в том, что даже через IL-асм принципиально нельзя сгенерить такой код, аналог которого нельзя было бы сгенерить через C#.
Вернее, можно, но валидацию такой код не пройдёт. ))
Поэтому, что бы там Синклер не нарисовал на IL-асме — оно или повторяемо ср-вами языка (хотя бы через прямой аналог, как в случае старинного трюка с генерацией "полезного" тела делегата), или "этого" не существует. Кароч, никакого волшебства тут нет и быть не может.
Re[31]: Аллокации
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.07.18 17:21
Оценка:
Здравствуйте, samius, Вы писали:

I>>Расскажи лучше, из за чего Linq тормозит. А то vdimas, alex_public и многие другие уверены, что из-за рефлексии, но не могут ни показать, не доказать

S>Расскажи, в каком конкретно случае и с чем именно сравниваем. А то мне за весь Linq как-то сложно отдуваться.

Я для смеху предложил. В КСВ уже месяц или два идет третий сезон, alex_public и vdimas жгут. Если интересно, можешь посмотреть. Эта тема плавно выросла из той
Re[28]: 2D-Linq и оптимизация цифровых фильтров - 3
От: vdimas Россия  
Дата: 09.07.18 17:31
Оценка:
Здравствуйте, IB, Вы писали:

S>>Специально перечитал посты Синклера. Идея сравнения скорости двумерного массива с одномерным — не его. Автор — vdimas. Причем здесь Синклер?

IB>Ну, просто у vdimas очень тонкая душевная организация. Ему оказывается тон сообщения Антона не понравился, вот и рвануло )

Это у тебя сейчас рвануло, как обычно.

А меня вначале заинтриговало, а потом наступило разочарование.
Пупочек-то у интригана надорвало.

B>А когда рвануло


Да ладно. ))
Вся подача Синклера — это результат разрыва мягкого органа.

Иначе бы он не напорол ошибок еще в первом же сообщении.
Скажи, неужели бока обещанного "решения" не были тебе видны еще с самого первого поста?

Походу, ты тоже загнал себя в слишком узкие рамки — или ты полный нуп, не умеющий прочитать и трех строчек кода, или ты на голубом глазу ведёшь нечестный спор (скорее всего по соображениям "корпоративной солидарности". )


IB>то все средства хороши — можно и не ту задачу не правильно решить


В отличие от синклера я как раз решил именно ту задачу — покрыл целый класс похожих алгоритмов.
Т.е. тебе опять двойка за неумение читать код.

Более того, ни в одном сообщении не указал, что у меня есть полный аналог кода Синклера, бо для соревнований нужны оба решения, ес-но, не только моё.
Т.е. мне еще требовалось бы проверить алгоритмы на идентичность работы, прежде чем давать отмашку на независимое сравнение.
Поэтому, тебе еще и кол за насос из пальца.


IB>а потом наехать на оппонента, чтобы все поняли кто виноват...


Я наехал на Синклера за его нечестность.
Отредактировано 09.07.2018 17:39 vdimas . Предыдущая версия . Еще …
Отредактировано 09.07.2018 17:37 vdimas . Предыдущая версия .
Отредактировано 09.07.2018 17:36 vdimas . Предыдущая версия .
Re[31]: Аллокации
От: Danchik Украина  
Дата: 09.07.18 17:32
Оценка: :)
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Ikemefula, Вы писали:


I>>Здравствуйте, samius, Вы писали:


S>>>И да, действительно там нет constrained TEnumerable/TEnumerator, вместо этого рекомендованная форма C<T>. Что вполне позволяет избегать боксинга.


I>>Расскажи лучше, из за чего Linq тормозит. А то vdimas, alex_public и многие другие уверены, что из-за рефлексии, но не могут ни показать, не доказать

S>Расскажи, в каком конкретно случае и с чем именно сравниваем. А то мне за весь Linq как-то сложно отдуваться.

Думаю становится третим КО не стоит. Им толкуют об одном, а они обсусоливают очевидные вещи о другом.
Re[32]: Аллокации
От: vdimas Россия  
Дата: 09.07.18 17:35
Оценка: -3
Здравствуйте, Ikemefula, Вы писали:

I>Я для смеху предложил. В КСВ уже месяц или два идет третий сезон, alex_public и vdimas жгут. Если интересно, можешь посмотреть. Эта тема плавно выросла из той


Это Синклер сбежал в зону комфорта, а я случайно мимо проходил. ))
В принципе, мне эти его бегания глубоко до одного места, но сами такие финты попахивают, однако.
Он в этом форуме неоднократно прошелся по Алексу, даже не пригласив того в обсуждение.
При том что тот заведомо сюда не заходит.
Это уже край мелочности.
Re[28]: 2D-Linq и оптимизация цифровых фильтров - 3
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.07.18 18:22
Оценка:
Здравствуйте, vdimas, Вы писали:

I>>Про рефлексию ты выразил согласие "Так и есть, это объективная реальность."


V>Там было не только про рефлексию, но мне лень обсуждать с тобой разницу происходящего в случае IEnumerable vs IQueryable.


Так ты расскажи про ту часть, где рефлексия тормозит и почему linq2db этого избежал
Re[29]: 2D-Linq и оптимизация цифровых фильтров - 3
От: vdimas Россия  
Дата: 09.07.18 21:00
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>>>Про рефлексию ты выразил согласие "Так и есть, это объективная реальность."

V>>Там было не только про рефлексию, но мне лень обсуждать с тобой разницу происходящего в случае IEnumerable vs IQueryable.
I>Так ты расскажи про ту часть, где рефлексия тормозит

Интерпретирование всегда тормозит.


I>и почему linq2db этого избежал


А он избежал?
Re[28]: 2D-Linq и оптимизация цифровых фильтров - 3
От: vdimas Россия  
Дата: 09.07.18 21:23
Оценка:
Здравствуйте, IB, Вы писали:

IB>А когда рвануло, то все средства хороши — можно и не ту задачу не правильно решить


Кстате, дошли руки дочитать ту ветку ваших обсуждений с Алексом, по итогам влепил тебе заслуженный минус за враньё.
Вы обсуждали некий класс задач, и соответствующих таким задачам ср-в эдакой "относительной адресации":

_>Более того, используемая для работы с коллекциями реализация (IEnumerable) является даже более ограниченной (только последовательный доступ), чем классический SQL, для которого в СУБД происходит интерпретация в императивный код.
FYI, linq — не завязан на IEnumerable и не ограничен последовательным доступом.


Ну и, помимо попытки лжи здесь о происходящем там, вижу, что там ты соврал о происходящем в C#, ибо:

The compiler infers the type of the range variable when the data source implements IEnumerable<T>.

Отредактировано 09.07.2018 22:47 vdimas . Предыдущая версия .
Re[31]: Аллокации
От: vdimas Россия  
Дата: 09.07.18 22:47
Оценка: :)
Здравствуйте, samius, Вы писали:

S>Linq — это технология интеграции запросов в язык. Она привязана к C<T> в спецификации.


Она привязана к IEnumerable/IQueryable и соответствующим методам типов или методов расширений, типа Select, Where и т.д.


S>Linq to Objects — это одна конкретная реализация.


Это единственная реализация, которая существует поверх IEnumerable<>
Переиначить её ты не сможешь не отказавшись от самого Linq. ))


S>Linq to SQL — еще одна.


Не одна, а целый класс их, например, Linq to XML, бо IQueryable требует провайдера для своей работы и принцип его работы отличается от Linq to objects кардинально.


S>Общего между этими реализациями ничего нет кроме того, что они удовлетворяют правилам трансляции запросов.


ИМХО, не идёт никакой речи об "удовлетворении правил", иначе можно было бы использовать другие интерфейсы, отличные от IEnumerable/IEnumerable<T>.
Но их использовать нельзя.
Получается, что правило тут одно — всё прибито гвоздями к двум интерфейсам, которые компилятор "знает в лицо". ))


S>Проведем мысленный эксперимент: уберем правило трансляции запросов — запросы остаются, интеграции в язык больше нет. Что общего между реализациями? Ничего. Осталось выяснить, что же тормозит.


Осталось выяснить, как создать нетормозящие и при этом неконфликтующие собственные реализации IEnumerable<>, типа как тут:
http://www.rsdn.org/forum/dotnet/7191943.1
И сверху них накрутить Linq.

Правильный ответ выглядит как "никак". ))
Из-за причин, описанных в последнем абзаце тут:
http://www.rsdn.org/forum/dotnet/7188517.1

Моментально возникают конфликты:
  пример
using System;
using System.Collections.Generic;

namespace ConsoleApp2
{
    public interface IMyEnumerable<T, out TEnumerator> //: IEnumerable<T>
        where TEnumerator : struct, IMyEnumerator<T> {
        TEnumerator GetEnumerator();
    }

    public interface IMyEnumerator<out T> {
        T Current { get; }
        bool MoveNext();
        void Reset();
    }

    public struct ArrayEnumerator<T> : IMyEnumerator<T> {
        private readonly T[] _array;
        private int _index;

        public ArrayEnumerator(T[] array) {
            _array = array;
            _index = -1;
        }

        public T Current => _array[_index];
        public bool MoveNext() => ++_index < _array.Length;
        public void Reset() => _index = -1;
    }

    public struct SelectEnumerator<TSrc, TSrcEnum, TDst> : IMyEnumerator<TDst>
        where TSrcEnum : IMyEnumerator<TSrc>
    {
        private TSrcEnum _src;
        private readonly Func<TSrc, TDst> _selector;

        public SelectEnumerator(TSrcEnum src, Func<TSrc, TDst> selector) {
            _src = src;
            _selector = selector;
            Current = default;
        }

        public TDst Current { get; private set; }

        public bool MoveNext() {
            if (_src.MoveNext()) {
                Current = _selector(_src.Current);
                return true;
            }

            return false;
        }

        public void Reset() => _src.Reset();
    }


    public struct SelectEnumerator<TSrc, TDst> : IMyEnumerator<TDst>
    {
        private readonly IEnumerator<TSrc> _src;
        private readonly Func<TSrc, TDst> _selector;

        public SelectEnumerator(IEnumerator<TSrc> src, Func<TSrc, TDst> selector)
        {
            _src = src;
            _selector = selector;
            Current = default;
        }

        public TDst Current { get; private set; }

        public bool MoveNext() {
            if (_src.MoveNext()) {
                Current = _selector(_src.Current);
                return true;
            }

            return false;
        }

        public void Reset() => _src.Reset();
    }

    public readonly struct SelectClause<TSrc, TSrcEnum, TDst>
        : IMyEnumerable<TDst, SelectEnumerator<TSrc, TSrcEnum, TDst>>
        where TSrcEnum : IMyEnumerator<TSrc>
    {
        private readonly TSrcEnum _srcEnum;
        private readonly Func<TSrc, TDst> _selector;

        public SelectClause(TSrcEnum srcEnum, Func<TSrc, TDst> selector) {
            _srcEnum = srcEnum;
            _selector = selector;
        }

        public SelectEnumerator<TSrc, TSrcEnum, TDst> GetEnumerator() =>
            new SelectEnumerator<TSrc, TSrcEnum, TDst>(_srcEnum, _selector);
    }

    public readonly struct SelectClause<TSrc, TDst>
        : IMyEnumerable<TDst, SelectEnumerator<TSrc, TDst>>
    {
        private readonly IEnumerator<TSrc> _srcEnum;
        private readonly Func<TSrc, TDst> _selector;

        public SelectClause(IEnumerator<TSrc> srcEnum, Func<TSrc, TDst> selector) {
            _srcEnum = srcEnum;
            _selector = selector;
        }

        public SelectEnumerator<TSrc, TDst> GetEnumerator() =>
            new SelectEnumerator<TSrc, TDst>(_srcEnum, _selector);
    }

    public static class MyLinqExtensions
    {
        public static SelectClause<TSource, TSrcEnum, TResult>
            Select<TSrcData, TSource, TSrcEnum, TResult>(this TSrcData source, Func<TSource, TResult> selector)
            where TSrcData : IMyEnumerable<TSource, TSrcEnum>
            where TSrcEnum : IMyEnumerator<TSource>
            => new SelectClause<TSource, TSrcEnum, TResult>(source.GetEnumerator(), selector);

        public static SelectClause<TSource, TResult>
            Select<TSrcData, TSource, TResult>(this TSrcData source, Func<TSource, TResult> selector)
            where TSrcData : IEnumerable<TSource>
            => new SelectClause<TSource, TResult>(source.GetEnumerator(), selector);
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var src = new ArrayEnumerator<int>(new[] {1, 2, 3});
            var q1 = from s in src select s + 1;    // Та-даам!!! 
            var q2 = from s in q1 select s + 1;

            foreach (var el in q2)
                Console.WriteLine(el);
        }
    }
}
Отредактировано 10.07.2018 0:01 vdimas . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.