Ваш вопрос: почему компилятор не понимает, что две линии
SomeMethod(x => OtherMethod(x));
SomeMethod(x => OtherMethod(x));
Одинаковы и писать это как
if (delegate is not created)
create the delegate and stash it away
SomeMethod(the delegate);
SomeMethod(the delegate);
? Хорошо, позвольте мне ответить на этот вопрос несколькими способами.
Прежде всего, является ли компилятор разрешенным, чтобы сделать эту оптимизацию? Да. В спецификации указано, что компилятор C# равен , разрешенному, чтобы сделать два лямбда, которые выполняют одну и ту же вещь в одном делетете. И на самом деле вы можете видеть, что он уже частично выполняет эту оптимизацию: он создает каждый делегат один раз и сохраняет его, так что ему не нужно создавать его снова позже, когда код вызывается снова. Обратите внимание, что это пустая трата памяти в случае, когда код вызывается только один раз.
Во-вторых, нужен ли компилятор , чтобы сделать оптимизацию кеширования? Нет. В спецификации указано, что компилятор только разрешен, чтобы сделать оптимизацию, но не требуется.
Требуется ли компилятор , чтобы сделать оптимизацию? Очевидно, нет, потому что это не так. Это разрешено, и, возможно, будущая версия компилятора будет. Компилятор является открытым исходным кодом; если вы заботитесь об этой оптимизации, напишите об этом и отправьте запрос на перенос.
В-третьих, это возможно, чтобы сделать оптимизацию, которую вы хотите? Да. Компилятор мог взять все пары лямбда, которые появляются в одном и том же методе, скомпилировать их во внутреннем древовидном формате и провести сравнение дерева, чтобы увидеть, есть ли у них одинаковый контент, а затем создать то же самое статическое поле поддержки для обоих.
Итак, теперь у нас есть ситуация: компилятор разрешил, чтобы сделать определенную оптимизацию, и это не так. И вы спросили «почему нет»? Это простой вопрос, чтобы ответить: все оптимизаций не выполняются до тех пор, пока кто-то тратит много времени и усилий на:
- Тщательно дизайн оптимизации: при каких именно условиях является оптимизация срабатывает и не срабатывает? Как вообще должна быть оптимизация? Вы предположили, что они обнаруживают подобные лямбда-тела, но зачем останавливаться там? У вас есть два идентичных оператора кода, так почему бы не сгенерировать код для этих операторов один раз вместо двух? Что делать, если у вас была повторная группа заявлений ?Здесь есть огромная проектная работа.
- В частности, важным аспектом конструкции является то, что пользователь может разумно выполнить оптимизацию «вручную», сохраняя при этом код читаемым. В этом случае, да, они могли бы, легко. Просто назначьте дублируемую лямбду переменной и затем используйте переменную. Оптимизация, которая автоматически делает то, что пользователь, который заботился, мог сделать легко, на самом деле не очень интересная или убедительная оптимизация.
- Ваши примеры тривиальны; реального кода нет. Что делает ваш предлагаемый дизайн с идентичными вложенными lambdas? И так далее.
- Выполняет ли ваша оптимизация поведение кода в отладчике, чтобы «выглядеть странным»? Вероятно, вы заметили, что при отладке кода, который был скомпилирован с оптимизацией, отладчик, похоже, ведет себя странно; это потому, что теперь нет четкого сопоставления между сгенерированным кодом и исходным кодом. Ваша оптимизация делает это хуже? Является ли он приемлемым для пользователей? Должен ли отладчик быть в курсе оптимизации? Если это так, вам придется изменить отладчик. В этом случае, вероятно, нет, но это вопросы, которые вы должны задать и ответить.
- Получить дизайн, рассмотренный экспертами; это занимает свое время и, скорее всего, приведет к изменениям в дизайне.
- Сделать оценки плюсов и минусов оптимизации. Оптимизация часто имеет скрытые затраты, такие как утечка памяти, о которой я упоминал ранее. В частности, оптимизации часто исключают другие оптимизации, которые могут быть лучше.
- Оцените общую экономию во всем мире этой оптимизации. Действительно ли оптимизация влияет на реальный код? Изменяет ли он правильность этого кода? Есть ли какой-либо производственный код в любой точке мира, который нарушит эту оптимизацию и заставит технический директора компании X вызывать технический директор Microsoft с требованием исправить? Если ответ «да», возможно, вам может понадобиться не делать эту оптимизацию. C# не игрушка. Ежедневно миллионы и миллионы людей зависят от правильной работы.
- Какова оценочная нагрузка на оптимизацию на время компиляции? Компиляция не должна происходить между нажатиями клавиш, но она должна быть довольно быстрой. Все, что вводит суперлинейный алгоритм в общий путь кода в компиляторе, будет неприемлемым. Можете ли вы реализовать свою оптимизацию, чтобы она была линейной по размеру кода? Обратите внимание, что алгоритм, который я набросал ранее, - сравнить все пары - является суперлинейным по размеру кода. (Упражнение: что в худшем случае асимптотическая производительность при сравнении дерева по всем парам лямбда?)
- На самом деле реализовать оптимизацию. Я призываю вас сделать это.
- Проверьте оптимизацию; действительно ли он дает лучший код? На какой метрике? Оптимизация, которая не приводит к изменению какой-либо метрики, не является оптимизацией.
- Зарегистрируйтесь, чтобы исправить ошибки в оптимизации навсегда.
Оптимизация, которую вы хотите, просто не соответствует полосе. Никто не пишет такой код. Если они это сделали, и они заботились о том, чтобы он продублировал объект, они могли легко исправить его сами. Таким образом, оптимизация оптимизирует код, который не существует, чтобы получить «выигрыш», который является построением одного объекта среди миллионов и миллионов объектов, которые программа выделит. Не стоит.
Но опять же, если вы так думаете, продолжайте и реализуйте его и отправьте запрос на тяну. Не забудьте представить результаты проведенных мной расследований, потому что это настоящая работа. Реализация, как правило, является наименьшей частью общего усилия, затраченного на функцию; поэтому C# - успешный язык.
SomeMethod (x => OtherMethod (x)); также имеет значение с 1 – becike
@becike, да, конечно. Я с тобой согласен. Но реализация кажется weird – LmTinyToon
, иначе я не уверен, что вы хотите, поскольку этот код не компилируется, поэтому вы пропустили пару частей – becike