Информация об изменениях

Сообщение Re[31]: Аллокации от 09.07.2018 22:47

Изменено 10.07.2018 0:01 vdimas

Re[31]: Аллокации
Здравствуйте, 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 SelectEnumerator<TSource, TSrcEnum, TResult>
            Select<TSrcData, TSource, TSrcEnum, TResult>(this TSrcData source, Func<TSource, TResult> selector)
            where TSrcData : struct, IMyEnumerable<TSource, TSrcEnum>
            where TSrcEnum : struct, IMyEnumerator<TSource>
            => new SelectEnumerator<TSource, TSrcEnum, TResult>(source.GetEnumerator(), selector);

        public static SelectEnumerator<TSource, TResult>
            Select<TSrcData, TSource, TResult>(this TSrcData source, Func<TSource, TResult> selector)
            where TSrcData : struct, IEnumerable<TSource>
            => new SelectEnumerator<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);
        }
    }
}
Re[31]: Аллокации
Здравствуйте, 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);
        }
    }
}