Здравствуйте, vdimas, Вы писали:
S>>Мультикастами могут быть только Action<...>.
V>Разве?
V>Что выведет:
V>V>Func<int> f1 = () => 42;
V>Func<int> f2 = () => 43;
V>Func<int> f3 = (Func<int>)Delegate.Combine(f1, f2);
V>WriteLine(f3());
V>
V>?
Выведет причину того, что комбинировать делегаты,
возвращающие значение, не имеет смысла. Более наглядным, возможно, будет следующий пример:
Func<int, bool> isEven = (x) => x % 2 == 0;
Func<int, bool> isXthree = (x) => x % 3 ==0;
Func<int, bool> combine = (Func<int, bool>)Delegate.Combine(isEven, isXthree);
foreach(var t in from r in Enumerable.Range(1, 10) where combine(r) select r)
Console.WriteLine(t);
V>Я про стандарт языка говорил.
V>Java Community Process был создан в 90-е, стандарт на язык был опубликован тогда же.
JCP появился в 1998, примерно через год после обсуждаемого иска.
V>Т.е., юридической основы для иска не было.
Ну, я не хочу сейчас лезть в юридические дебри. Интересно пофантазировать, что было бы, если бы не было этого иска и мирового соглашения.
Возможно, мы сейчас бы жили в мире, где дотнета нет, зато есть java с value-типами и нормальными генериками, а не этой порнографией.
То есть вместо двух управляемых платформ мы бы имели одну, сочетающую лучшие стороны обеих.
V>Про дотнет.
Ок, а то было непонятно.
V>В нашей компании всё стандартно — ресурсы перекидываются по велению руководства.
Ну вот в нашей компании ресурсы, конечно, перекидываются по велению руководства, но продакт менеджмент стоит достаточно близко к руководству, чтобы а) понимать, на основании чего перекидываются ресурсы и б) в определённой степени влиять на приоритеты.
V>В случае нестатик возможны неоднозначности, которые непонятно как решать.
V>Например, без локальных ф-ий происходящее очевидно:
V>V> var expressions = new List<Expression<Func<int>>>();
V> for(var i = 0; i < 4; i++)
V> expressions.Add(() => i);
V> expressions.ForEach(e => Console.WriteLine(e.Compile()()));
V>
V>Выведет
V>V>4
V>4
V>4
V>4
V>
V>О захвате мутабельной переменной i компилятор честно выдаст warning при компиляции.
V>Но локальная ф-ия может скрыть свою мутабельную природу.
Ну, в таком случае — почему работает вот это?
int i=0;
Func<int> getI = () => i;
var expressions = new List<Expression<Func<int>>>();
for(i = 0; i < 4; i++)
expressions.Add(() => getI());
expressions.ForEach(e => Console.WriteLine(e.Compile()()));
То есть анонимную локальную функцию — можно, безо всяких ворнингов, а именованную — уже нельзя.
Почему можно вот так?
int i=0;
int getI() => i;
var callbacks = new List<Func<int>>();
for(i = 0; i < 4; i++)
callbacks.Add(() => getI());
callbacks.ForEach(e => Console.WriteLine(e()));
То есть в делегате ссылаться на потенциально нечистую функцию — ок, а в expression — уже зашквар?
V>А как обеспечить чистоту функций на уровне языка — непонятно.
Это опять рационализация иррационального.
V>Про локальные я полностью согласен — это непредсказуемая дичь в случае Expression и обычных делегатов, т.к. не всегда очевидно, что именно захватывается и где, т.к. таких локальных ф-ий может быть несколько, но они шарят общий контекст.
Как видим, в случае делегатов это никому не мешает.
V>Но статические локальные ф-ии чисты относительно контекста, т.е. не подменяют значений и ссылок локальных переменных.
Правильный ответ — локальные функции настолько редко используются в делегатах и выражениях, что всем просто наплевать.
V>Может, понимает, что не пройдёт.
V>Или видит недостаточный приоритет этой задаче.
V>Разобрать серьезный PR — это не лужу перешагнуть.
V>У нас на работе как начинаю разбирать... Иногда ловишь себя на мысли, что быстрее было самому сделать чем тщательно объяснять десяток одновременно участвующих тонкостей.
V>А в его коде этих тонкостей сотни.
V>Это нужна приличная команда для верификации такого PR, которая будет много дней разбирать его код.
Надо будет ему написать и спросить.