| 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);
}
}
}
|