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

Сообщение Re[49]: «Собаку съел» от 20.01.2017 16:14

Изменено 20.01.2017 16:23 Serginio1

Re[49]: «Собаку съел»
Здравствуйте, samius, Вы писали:

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


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


S>>>Т.е. если компаратор заранее известен, то никакого отношения к инлайну дженерикового компаратора это не имеет.


S>> Угу, а как же шаблоны то инлайнят функции при специализации, если компаратор не известен

S>В момент специализации шаблона он известен.

S>>Еще раз


S>>
S>>public static IEnumerable<TSource> Where<TSource>(
S>>    this IEnumerable<TSource> source,
S>>    Func<TSource, bool> predicate
S>>)
S>>


S>> Здесь как ты видишь дженерик метод Func<TSource, bool> predicate

S>>При этом автоматически выводится тип.
S>Дженерик метод, точнее делегат и выводящийся тип я вижу. Я не вижу здесь дженерикового компаратора. Его в этом примере нет, изначально есть лишь оператор сравнения для Int32. И в процессе инлайна Where и т.п., вызов оператора сравнения Int32 остается самим же собой. Т.е. с ним абсолютно ничего не происходит.
Изначально происходит специализация как и в шаблонах C++
а Func<TSource, bool> predicate учавствует в дженерик коде .

S>>>Инлайнится Where, Select и Sum, функция, принимающая целый x и сравнивающая с q, функция, добавляющая целому 3. Но никак не компаратор и оператор сложения. Параметрически полиморфны здесь Where и Select, но не компаратор, сложение и Sum.


S>> Еще раз, нет никаких особых препятствий для инлайнинга сомпараторов при специализации как это делается в C++.

S>Препятствий-то нет, но и инлайнинга тоже нет.

А откуда ты з-наешь?
S>>При этом в том же Net Native как раз это и происходит.
S>Можно ссылку? Еще раз уточню, я ожидаю увидеть автоматический разворот обобщенного компаратора Compare<T>(T, T) в специальный для типа T. Именно это я подразумеваю под инлайном дженерикового компаратора.
Вот смотри исходники

https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs

А вот как это разворачивается

Optimising LINQ

roslyn-linq-rewrite



Так Func<TSource, bool> predicate
это и есть компаратор. Он и разворачивается.
Re[49]: «Собаку съел»
Здравствуйте, samius, Вы писали:

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


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


S>>>Т.е. если компаратор заранее известен, то никакого отношения к инлайну дженерикового компаратора это не имеет.


S>> Угу, а как же шаблоны то инлайнят функции при специализации, если компаратор не известен

S>В момент специализации шаблона он известен.

S>>Еще раз


S>>
S>>public static IEnumerable<TSource> Where<TSource>(
S>>    this IEnumerable<TSource> source,
S>>    Func<TSource, bool> predicate
S>>)
S>>


S>> Здесь как ты видишь дженерик метод Func<TSource, bool> predicate

S>>При этом автоматически выводится тип.
S>Дженерик метод, точнее делегат и выводящийся тип я вижу. Я не вижу здесь дженерикового компаратора. Его в этом примере нет, изначально есть лишь оператор сравнения для Int32. И в процессе инлайна Where и т.п., вызов оператора сравнения Int32 остается самим же собой. Т.е. с ним абсолютно ничего не происходит.
Изначально происходит специализация как и в шаблонах C++
а Func<TSource, bool> predicate учавствует в дженерик коде .

S>>>Инлайнится Where, Select и Sum, функция, принимающая целый x и сравнивающая с q, функция, добавляющая целому 3. Но никак не компаратор и оператор сложения. Параметрически полиморфны здесь Where и Select, но не компаратор, сложение и Sum.


S>> Еще раз, нет никаких особых препятствий для инлайнинга сомпараторов при специализации как это делается в C++.

S>Препятствий-то нет, но и инлайнинга тоже нет.

А откуда ты з-наешь?
S>>При этом в том же Net Native как раз это и происходит.
S>Можно ссылку? Еще раз уточню, я ожидаю увидеть автоматический разворот обобщенного компаратора Compare<T>(T, T) в специальный для типа T. Именно это я подразумеваю под инлайном дженерикового компаратора.
Вот смотри исходники

https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs

А вот как это разворачивается

Optimising LINQ

roslyn-linq-rewrite



Так Func<TSource, bool> predicate
это и есть компаратор. Он и разворачивается.

То есть

 while (enumerator.MoveNext()) {
                            TSource item = enumerator.Current;
                            if (predicate(item)) {
                                current = item;
                                return true;
                            }
                        }


Прекрасно разворачивается

Example input code


public int Method1()
{
    var arr = new[] { 1, 2, 3, 4 };
    var q = 2;
    return arr.Where(x => x > q).Select(x => x + 3).Sum();
}

Allocations: input array, array enumerator, closure for q , Where delegate, Select delegate, Where enumerator, Select enumerator.

Decompiled output code


public int Method1()
{
    int[] arr = new[] { 1, 2, 3, 4 };
    int q = 2;
    return this.Method1_ProceduralLinq1(arr, q);
}
private int Method1_ProceduralLinq1(int[] _linqitems, int q)
{
    if (_linqitems == null) throw new ArgumentNullException();

    int num = 0;
    for (int i = 0; i < _linqitems.Length; i++)
    {
        int num2 = _linqitems[i]; 
        if (num2 > q)
            num += num2 + 3;
    }
    return num;
}