Re[8]: C# - добавили бардака - одобряете?
От: IT Россия linq2db.com
Дата: 08.09.22 21:44
Оценка: 18 (1) +2
Здравствуйте, karbofos42, Вы писали:

K>Люди для List вместо проверки Count вызывают метод Any(). Вместо нулевого элемента запрашивают First().


Рекомендую поизучать исходники Linq.

        public static bool Any<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            if (source is ICollection<TSource> collectionoft)
            {
                return collectionoft.Count != 0;
            }
            else if (source is IIListProvider<TSource> listProv)
            {
                // Note that this check differs from the corresponding check in
                // Count (whereas otherwise this method parallels it).  If the count
                // can't be retrieved cheaply, that likely means we'd need to iterate
                // through the entire sequence in order to get the count, and in that
                // case, we'll generally be better off falling through to the logic
                // below that only enumerates at most a single element.
                int count = listProv.GetCount(onlyIfCheap: true);
                if (count >= 0)
                {
                    return count != 0;
                }
            }
            else if (source is ICollection collection)
            {
                return collection.Count != 0;
            }

            using (IEnumerator<TSource> e = source.GetEnumerator())
            {
                return e.MoveNext();
            }
        }


С First примерно та же ситуация.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: C# - добавили бардака - одобряете?
От: vaa  
Дата: 09.09.22 01:27
Оценка:
Здравствуйте, Aquilaware, Вы писали:



A>Например, классика:


A>
A>var bicycle = TryGetBicycle();
A>if (bicycle != null)

или просто 
[cs]
dynamic boo = getboo();
foo(boo);

void foo(A b);
void foo(B b);
void foo(C b);
void foo(object b);
☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 09.09.2022 1:32 Разраб . Предыдущая версия .
Re: C# - добавили бардака - одобряете?
От: vaa  
Дата: 09.09.22 01:29
Оценка: :)
Здравствуйте, Shmj, Вы писали:

S>Теперь можно писать и так и эдак:


S>Не кажется ли это внедрением бардака? В одном месте будут писать так в другом эдак.


Так не юзай ЯП с синтаксисами!
есть же жемчужина программирования:
https://lisp-lang.org/
https://common-lisp.net/
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[9]: C# - добавили бардака - одобряете?
От: karbofos42 Россия  
Дата: 09.09.22 04:32
Оценка: :)
Здравствуйте, IT, Вы писали:

IT>Рекомендую поизучать исходники Linq.


Так я видел и в курсе.
Разве нет разницы между items[0] и items.First() в плане, что во втором случае добавляется проверка типа коллекции?
Вроде мелочь, а вроде лишняя работа и лишнее ветвление непонятно зачем.
Last() хоть короче и понятнее записывается, чем items[items.Count — 1], а с First вообще одни минусы, как по мне.
Re[10]: C# - добавили бардака - одобряете?
От: Евгений Акиньшин grapholite.com
Дата: 09.09.22 05:58
Оценка: +2
Здравствуйте, karbofos42, Вы писали:


K>Last() хоть короче и понятнее записывается, чем items[items.Count — 1], а с First вообще одни минусы, как по мне.


В современном си шарпе пишут:

items[^1]
Не шалю, никого не трогаю, починяю примус Diagrams Designer for iPad and Windows 10
Re[2]: C# - добавили бардака - одобряете?
От: karbofos42 Россия  
Дата: 09.09.22 06:01
Оценка: +2 :)
Здравствуйте, Aquilaware, Вы писали:

A>Можно даже захватить походящее значение в переменную для дальнейшего использования:


A>
A>if (GetIQ() is < 100 and > 50 and var iq)
A>    Console.WriteLine("Hoi polloi IQ: {0}", iq);
A>


А что будет, если написать or var iq?
Почему не запись типа:
A>
A>if (var iq = GetIQ() is < 100 and > 50)
A>    Console.WriteLine("Hoi polloi IQ: {0}", iq);
A>

в язык не вписалось?
Возможность сама вроде норм, но выглядит то убого и чужеродно

A>Теперь вы видите?


Я лично тут вижу, что кто-то написал кривые методы, которые неудобно использовать и в результате вокруг них идут какие-то костыли.
Что мешало написать так:
if (TryGetBicycle(out var bicycle))
...
else if (TryGetMotorcycle(out var motorcycle))
...
else
...

и запись короче и язык коверкать не нужно
Re[9]: C# - добавили бардака - одобряете?
От: Shtole  
Дата: 09.09.22 07:53
Оценка:
Здравствуйте, Слава, Вы писали:

С>Представьте список транзакций, к каждой из которых нужно добавить набор разрешённых действий. У транзакции есть набор признаков, штук 15.

С>Сейчас это сделано в виде 400* строк вложенных if'ов, и одно и то же действие может быть добавлено в нескольких местах этой скомканной простыни. Разбираться в этом очень тяжело.

PM уважаю, как и функциональный подход в принципе, но в данном случае вопрос: а нельзя ли как-то это всё «раскодировать» (перевести из кода во что-то другое)? Или в DSL, или в data-файл. Я бы в эту сторону подумал.
Do you want to develop an app?
Отредактировано 09.09.2022 10:22 Shtole . Предыдущая версия .
Re[2]: C# - добавили бардака - одобряете?
От: Shtole  
Дата: 09.09.22 08:17
Оценка: +1
Здравствуйте, Aquilaware, Вы писали:

A>Вместо такого ужаса теперь посмотрим на произведение исскуства, на картину Художника:


A>
A>if (TryGetBicycle() is not null and var bicycle)
A>    Console.WriteLine("Bicycle owner is {0}.", bicycle.Owner);
A>else if (TryGetMotorcycle() is not null and var motorcycle)
A>    Console.WriteLine("Motorcycle owner is {0}.", motorcycle.Owner);
A>else if (TryGetCar() is not null and var car)
A>    Console.WriteLine("Car owner is {0}.", car.Owner);
A>else
A>    // ... красота на любом уровне "вложенности"! ...
A>


Для произведения искусства тут слишком много копипасты. Как по мне, я бы сделал список типов (Bicycle, Motorcycle, Car) и проверял соответствие каждому, а при выводе в консоль использовал бы метаданные (имя типа или назначенная ему человекочитаемая строка). А если бы набор TryGetX() был внешним и не поддавался переписыванию, сделал бы список хотя бы методов (TryGetBicycle, TryGetMotorcycle, TryGetCar).
Do you want to develop an app?
Отредактировано 14.09.2022 14:14 Shtole . Предыдущая версия .
Re[11]: C# - добавили бардака - одобряете?
От: karbofos42 Россия  
Дата: 09.09.22 09:04
Оценка: :)
Здравствуйте, Serginio1, Вы писали:

S>Угу если источник будет меняться, то получишь, что угодно. Суть понимать с чем имеешь дело.


Ну, вот и у linq я вижу варианты использования и это нужная вещи, а у этого кривого синтаксического сахара — нет.
Возможно где-то его использование и оправдано и у меня просто таких задач не было.
Предвижу, что раньше люди боялись объёмных ветвлений и начинали задумываться над архитектурой, переписывая нормально, что такие проверки становились в принципе не нужны.
Теперь объёмные проверки можно легко и коротко записывать, поэтому чего бы дублирующих условий везде не напихать и плевать как это скажется на производительности и сколько лишнего будет код делать.
Re[3]: C# - добавили бардака - одобряете?
От: Aquilaware  
Дата: 09.09.22 10:55
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>
K>if (TryGetBicycle(out var bicycle))
K>

K>и запись короче и язык коверкать не нужно

То, что предлагаете вы — это никак не ровные методы, это исторический костыль. Проблема с этим костылем в том, что нельзя сделать вот так:

var vehicle = TryGetBicycle() ?? TryGetMotorcycke() ?? TryGetCar();


А нужно как всегда извращаться в упражнении рука-писать. Это прям как в Java, где нет out и ref параметров функций, и поэтому люди вынуждены придумывать свои исторические костыли.

Зачем, если всё это можно сделать средствами языка? Например, был бы полноценный Optional<T> или уже сам тип данных подразумевает null значение.
Re[2]: C# - добавили бардака - одобряете?
От: Aquilaware  
Дата: 09.09.22 11:08
Оценка: 56 (2)
Здравствуйте, vaa, Вы писали:

vaa>есть же жемчужина программирования:

vaa>https://lisp-lang.org/
vaa>https://common-lisp.net/

Lisp — это святое. Кстати, если бы топик стартер поупражнялся в нем, то он бы не создавал подобных тем, так как Lisp человеку помагает осознать саму материю языка. Прикоснуться к ядру компьютерной и математической вселенной, к тому, с чего начинается само понятие вычисления.

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

Рекомендуется всем, кто не ещё пробовал. Но конечно же, большая часть людей проигнорирует эту возможность по разным причинам. Кто-то закатит глаза со словами "опять эта функциональщина, а мне тут формы шлёпать надо", у кого-то не будет времени из-за занятости, а кто-то вообще не поймет, что тут такого особенного происходит.
Re[4]: C# - добавили бардака - одобряете?
От: karbofos42 Россия  
Дата: 09.09.22 12:21
Оценка: :)
Здравствуйте, Aquilaware, Вы писали:

A>То, что предлагаете вы — это никак не ровные методы, это исторический костыль. Проблема с этим костылем в том, что нельзя сделать вот так:


не костыль, а try-parse паттерн же

A>А нужно как всегда извращаться в упражнении рука-писать.


ну, для предыдущего варианта подвезли pattern-matching, могли и для этого что-то в язык тогда добавить, чтобы удобнее было использовать
Re[10]: C# - добавили бардака - одобряете?
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.09.22 13:53
Оценка:
Здравствуйте, karbofos42, Вы писали:
K>Так я видел и в курсе.
K>Разве нет разницы между items[0] и items.First() в плане, что во втором случае добавляется проверка типа коллекции?
Если вас действительно интересует такой вопрос — не поленитесь и посмотрите дизассемблером.
Микроскопические методы типа First прекрасно инлайнятся, а проверки типа в случаях, когда тип известен (то есть как раз там, где можно безопасно написать items[0]), устраняются JIT-ом.
А если этот вопрос вас не беспокоит, то старайтесь писать понятный код, дружественный к модификациям. items.First() точнее выражает намерение разработчика и дружелюбнее к будущей смене типа коллекции.
K>Вроде мелочь, а вроде лишняя работа и лишнее ветвление непонятно зачем.
K>Last() хоть короче и понятнее записывается, чем items[items.Count — 1], а с First вообще одни минусы, как по мне.
Пока что минусов не видно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: C# - добавили бардака - одобряете?
От: Слава  
Дата: 09.09.22 17:02
Оценка:
Здравствуйте, Shtole, Вы писали:

S>PM уважаю, как и функциональный подход в принципе, но в данном случае вопрос: а нельзя ли как-то это всё «раскодировать» (перевести из кода во что-то другое)? Или в DSL, или в data-файл. Я бы в эту сторону подумал.


Для этого нужен отбеливатель и шуруповёрт с набором саморезов. В отбеливатель засунуть исполнительных копчёных сотрудников, а шуруповёртом закрутить саморезы в головы белым энергичным сотрудникам. А без этого они так и будут тикеты создавать и закрывать.
Re[11]: C# - добавили бардака - одобряете?
От: karbofos42 Россия  
Дата: 09.09.22 17:26
Оценка: 127 (3) :)
Здравствуйте, Sinclair, Вы писали:

S>Если вас действительно интересует такой вопрос — не поленитесь и посмотрите дизассемблером.

S>Микроскопические методы типа First прекрасно инлайнятся, а проверки типа в случаях, когда тип известен (то есть как раз там, где можно безопасно написать items[0]), устраняются JIT-ом.

Посмотрел через ILSpy, посмотрел на sharplab, вызов метода First никуда не делся.
Я не силён в устройстве компилятора и т.п. Метод First точно может инлайниться? Он вроде в другой сборке лежит, а не в моём проекте, такое инлайнится?

S>А если этот вопрос вас не беспокоит, то старайтесь писать понятный код, дружественный к модификациям. items.First() точнее выражает намерение разработчика и дружелюбнее к будущей смене типа коллекции.


Ну, да. Мне тут намедни таск под ускорение метода прилетел. Изменил 1 строчку и получил ускорение в десяток раз.
Кто-то взял List и для него активно вызывал методы Remove и Contains. Простая замена на HashSet дала достаточный прирост скорости.
Только пришлось всё равно пробежать по коду и убедиться, что там не важен порядок элементов и я сменой коллекции ничего не нарушу.
Если бы мне пришлось попутно поменять [0] на .First(), то вот вообще не переживал бы.
А я мог и не посмотреть и не думать об особенностях и различиях обеих коллекций.
Засунул бы HashSet бездумно туда, где важен порядок элементов, лови потом весёлый баг.

S>Пока что минусов не видно.


Давно хотел и вот решил под такое дело таки попробовать BenchmarkDotNet.
  Код теста
public class Benchmark
{
    const int retry = 10;
    List<int> _items;

    public Benchmark()
    {
        _items = new List<int>(1);
        _items.Add(1);
    }

    [Benchmark]
    public bool ByAny()
    {
        bool result = false;
        for (int i = 0; i < retry; ++i)
        {
            result = _items.Any();
        }
        return result;
    }

    [Benchmark]
    public bool ByCount()
    {
        bool result = false;
        for (int i = 0; i < retry; ++i)
        {
            result = _items.Count != 0;
        }
        return result;
    }

    [Benchmark]
    public int ByIndex()
    {
        int result = 0;
        for (int i = 0; i < retry; ++i)
        {
            result = _items[0];
        }
        return result;
    }

    [Benchmark]
    public int ByFirst()
    {
        int result = 0;
        for (int i = 0; i < retry; ++i)
        {
            result = _items.First();
        }
        return result;
    }
}


  Результат
BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19044.1526/21H2/November2021Update)
Intel Core i3-10100F CPU 3.60GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=6.0.400
  [Host]     : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
  DefaultJob : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2


|  Method |       Mean |     Error |    StdDev |
|-------- |-----------:|----------:|----------:|
|   ByAny |  47.657 ns | 0.3115 ns | 0.2761 ns |
| ByCount |   3.235 ns | 0.0304 ns | 0.0285 ns |
| ByIndex |   6.913 ns | 0.0838 ns | 0.0784 ns |
| ByFirst | 108.889 ns | 1.4484 ns | 1.3549 ns |


Я что-то не так сделал или всё же разница в разы есть?
Re[12]: C# - добавили бардака - одобряете?
От: Sinclair Россия https://github.com/evilguest/
Дата: 10.09.22 03:20
Оценка: +1
Здравствуйте, karbofos42, Вы писали:
K>Посмотрел через ILSpy, посмотрел на sharplab, вызов метода First никуда не делся.
Это очень интересно. Действительно, почему-то вызов остаётся.
K>Я не силён в устройстве компилятора и т.п. Метод First точно может инлайниться? Он вроде в другой сборке лежит, а не в моём проекте, такое инлайнится?
Да, такое должно инлайниться. Почему этого не происходит — отдельный вопрос.
Будет время — я посмотрю логи джита.
K>Ну, да. Мне тут намедни таск под ускорение метода прилетел. Изменил 1 строчку и получил ускорение в десяток раз.
K>Кто-то взял List и для него активно вызывал методы Remove и Contains. Простая замена на HashSet дала достаточный прирост скорости.
И это — очень типичная ситуация. Примерно так и выглядит оптимизация шарпа в 99% случаев.
K>Только пришлось всё равно пробежать по коду и убедиться, что там не важен порядок элементов и я сменой коллекции ничего не нарушу.
В идеальном случае пробежка выполняется при помощи перепрогона тестов. Если тестов мало — то да, надо смотреть глазами.
Хотя это менее надёжно — мало ли, что где можно посмотреть.
K>Если бы мне пришлось попутно поменять [0] на .First(), то вот вообще не переживал бы.
K>А я мог и не посмотреть и не думать об особенностях и различиях обеих коллекций.
K>Засунул бы HashSet бездумно туда, где важен порядок элементов, лови потом весёлый баг.

K>| Method | Mean | Error | StdDev |

K>|-------- |-----------:|----------:|----------:|
K>| ByAny | 47.657 ns | 0.3115 ns | 0.2761 ns |
K>| ByCount | 3.235 ns | 0.0304 ns | 0.0285 ns |
K>| ByIndex | 6.913 ns | 0.0838 ns | 0.0784 ns |
K>| ByFirst | 108.889 ns | 1.4484 ns | 1.3549 ns |
K>[/code]
K>[/cut]

K>Я что-то не так сделал или всё же разница в разы есть?

Вы всё сделали верно. Снимаю шляпу. На досуге поразбираюсь, откуда такой провал в производительности.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: C# - добавили бардака - одобряете?
От: vsb Казахстан  
Дата: 10.09.22 03:36
Оценка:
Здравствуйте, Aquilaware, Вы писали:

A>Поэтому задание для топик стартера — это написать своими руками интерпретатор Scheme (нормализованного диалекта Lisp) и в процессе прочувствовать это всё. После такого опыта дороги назад уже не будет, настолько сильным будет его влияение на сознание и на понимание происходящих процессов.


A>Рекомендуется всем, кто не ещё пробовал. Но конечно же, большая часть людей проигнорирует эту возможность по разным причинам. Кто-то закатит глаза со словами "опять эта функциональщина, а мне тут формы шлёпать надо", у кого-то не будет времени из-за занятости, а кто-то вообще не поймет, что тут такого особенного происходит.


Я писал. Компилятор даже. Нет, не понял, что там особого. Ничего особого в схеме нет. Убогий игрушечный недоязычок, даже до джаваскрипта не дотягивает. А уж интерпретатор — там и вовсе ничего интересного. С компилятором там хоть какие-то вопросы возникают в голове.

Вот хаскель — да. Там ничего писать не надо. Просто сидеть и учить, фича за фичей. Подбирая выпадающий мозг.
Отредактировано 10.09.2022 3:39 vsb . Предыдущая версия . Еще …
Отредактировано 10.09.2022 3:37 vsb . Предыдущая версия .
Отредактировано 10.09.2022 3:36 vsb . Предыдущая версия .
Re[11]: C# - добавили бардака - одобряете?
От: Евгений Акиньшин grapholite.com
Дата: 10.09.22 04:33
Оценка: 122 (4)
Здравствуйте, Sinclair, Вы писали:

K>>Last() хоть короче и понятнее записывается, чем items[items.Count — 1], а с First вообще одни минусы, как по мне.

S>Пока что минусов не видно.

А бывает еще смешней: в .net7 linq методы кое-где используют векторизацию и могут работать в 10-ки раз быстрее, чем очевидная реализация руками:

https://youtu.be/zCKwlgtVLnQ
Не шалю, никого не трогаю, починяю примус Diagrams Designer for iPad and Windows 10
Re[13]: C# - добавили бардака - одобряете?
От: Sinclair Россия https://github.com/evilguest/
Дата: 10.09.22 04:59
Оценка: 8 (2)
Здравствуйте, Sinclair, Вы писали:

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

K>>Посмотрел через ILSpy, посмотрел на sharplab, вызов метода First никуда не делся.
S>Это очень интересно. Действительно, почему-то вызов остаётся.
З.Ы. Посмотрел врукопашную, взяв исходник из Core https://github.com/dotnet/runtime/blob/80b7a657ee1471f20fd23f228b2576c0dbe14789/src/libraries/System.Linq/src/System/Linq/First.cs
Применение AggessiveInlining на First и TryGetFirst помогает встроить код, но в итоге почему-то всё равно остаются вызовы.
Похоже, основные оптимизации JIT попали на value-типы, а для референс-типов вроде List<T> устраняется не вся возможная косвенность.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: C# - добавили бардака - одобряете?
От: Caracrist https://1pwd.org/
Дата: 11.09.22 11:58
Оценка: +1
Здравствуйте, Aquilaware, Вы писали:

A>var bicycle = TryGetBicycle();
A>if (bicycle != null)
A>    Console.WriteLine("Bicycle owner is {0}.", bicycle.Owner);
A>


A>это теперь можно делать в одну строку:


A>if (TryGetBicycle() is not null and var bicycle)
A>    Console.WriteLine("Bicycle owner is {0}.", bicycle.Owner);
A>


A>Почему такая возможность важна? Потому что иногда это безумно удобно во вложенных if'ах, так как позволяет обойтись одним уровнем вложенности вместо плохо читаемой "ёлочки" c углублениями.


Могли бы взять синтаксис C++17

Получилось бы тоже в одну строчку:
if (var bicycle = TryGetBicycle(); bicycle != null)
    Console.WriteLine("Bicycle owner is {0}.", bicycle.Owner);

~~~~~
~lol~~
~~~ Single Password Solution
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.