Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>>Про чинить компилятор спрашивал, ответ — заведи отдельный метод и не страдай фигнёй
S>>А можно спросить, где явная реализация explicit строки к FormattableString? Совсем отстал от жизни S>Я сейчас явно торможу, т.к. вообще не понял вопрос
S>Можешь как-нибудь переформулировать?
Откуда приведение строки к FormattableString?
Assert(x > 0, (FormattableString)$"Value of x ({x}) be should be greater than zero.");
и солнце б утром не вставало, когда бы не было меня
Re[10]: Interpolated strings: есть идеи, как подправить прои
А, там прикол в следующем: если нет другой подходящей перегрузки, как вот тут:
// Других перегрузок нетstatic void AssertState(bool condition, IFormattable message)
{
if (!condition)
throw new InvalidOperationException(message.ToString());
}
то авторы шарпа считают, что сгенерить FormattableString — это нормально.
(в параметре использован IFormattable вместо FormattableString, т.к. собирается под 4.5, там FormattableString нет)
А вот если рядом есть перегрузка с строкой, то использовать FormattableString внезапно становится некомильфо — перегрузка для FormattableString автоматом не выберется никогда, только если явный каст сделать.
UPD ещё одно следствие этого решения — extension-методов для interpolated string не работают.
Т.е.
$"Version {2.0}".InvariantCulture(); // Version 2.0 even with Russian locale
не сработает. На что я уже напоролся в пришедшем с продакшна логе — парсер благополучно сломался на числах, выведенных в левой культуре.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Откуда приведение строки к FormattableString?
S>А, там прикол в следующем: если нет другой подходящей перегрузки, как вот тут: S>
S> // Других перегрузок нет
S> static void AssertState(bool condition, IFormattable message)
S> {
S> if (!condition)
S> throw new InvalidOperationException(message.ToString());
S> }
S>
S>то авторы шарпа считают, что сгенерить FormattableString — это нормально. S>(в параметре использован IFormattable вместо FormattableString, т.к. собирается под 4.5, там FormattableString нет)
S>А вот если рядом есть перегрузка с строкой, то использовать FormattableString внезапно становится некомильфо — перегрузка для FormattableString автоматом не выберется никогда, только если явный каст сделать.
Это я понимаю. То есть
строка $"Value of x ({x}) be should be greater than zero."); не что иное как IFormattable ?
Здравствуйте, Пельмешко, Вы писали:
П>Я до сих пор не могу понять, пользователи действительно считают что решарпер пишут тупые фичеписцы, или просто когда критикуешь решарпер почему-то не хочется думать что за инспекциями стоял какой-то здравый смысл...
… П>Что касается проблемы с assert-методами: мы просто продолбали этот сценарий, …
П>…который конечно здорово подкашивает веру в единообразие кода форматирования строк
Это полдела; важнее, что заставляет думать о первом ("что решарпер пишут…") Вот опубликуй вы какой-нить "Кодекс РеШарпера", из которого пользователям было бы ясно, как вы себе представляете код, который они, пользователи, пишут и где вы видите ту асимптоту, к которой считаете нужным приблизить этот код — не пришлось бы обижаться на такие подозрения. Сказали бы просто — зри в кодекс, в нашу модель пользовательского кода.
И интересно было бы многим, и с тонкими такими моментами стало бы ясно что делать: просить до- или перепилить или настроить сразу себе правила.
П>Мы определенно подточим инспекцию … П>Мы вас слышим и обязательно починим этот кейс, спасибо большое что вынесли на обсуждение!
Re[12]: Interpolated strings: есть идеи, как подправить прои
Здравствуйте, Sinix, Вы писали: S>А вот если рядом есть перегрузка с строкой, то использовать FormattableString внезапно становится некомильфо — перегрузка для FormattableString автоматом не выберется никогда, только если явный каст сделать.
Интересно, что помешало им всегда генерить FormattableString, и добавить в него implicit conversion в System String.
Тогда бы всё работало как интуитивно ожидается c точки зрения перегрузки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Interpolated strings: есть идеи, как подправить прои
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Sinix, Вы писали: S>>А вот если рядом есть перегрузка с строкой, то использовать FormattableString внезапно становится некомильфо — перегрузка для FormattableString автоматом не выберется никогда, только если явный каст сделать. S>Интересно, что помешало им всегда генерить FormattableString, и добавить в него implicit conversion в System String. S>Тогда бы всё работало как интуитивно ожидается c точки зрения перегрузки.
Помимо перегрузок есть еще много всего.
Например, если сделать как ты предлагаешь, то:
string str = "Hello, world";
string world = "world";
if (str.Equals($"Hello, {world}"))
{
// А сюда мы не попадем string.Equals(FormatableString) очевидно вернет false
}
Здравствуйте, Sinclair, Вы писали:
S>Интересно, что помешало им всегда генерить FormattableString, и добавить в него implicit conversion в System String. S>Тогда бы всё работало как интуитивно ожидается c точки зрения перегрузки.
Как я понял, тогда был бы нужен костыль для случаев
var s = $"Hello, {Name}!";
чтоб s был строкой.
Точнее, пришлось бы добавить оптимизацию компилятора — заменять FormattableString на string.Format(...), если FormattableString не нужен.
Ну и плюс отразить это всё внятно в спецификации, тоже задача не из лёгких.
Чтоб было совсем весело — изменение затрагивает overload resolution (сразу сложность x10) + поведение должно быть одинаковым что для dynamic, что для expression trees.
Но это чисто моё мнение, официальное лучше в issues рослина спросить.
Re: Interpolated strings: есть идеи, как подправить производител
Здравствуйте, Venom, Вы писали:
V>А как ты затаргетил на 4.5? V>У меня при таргете 4.5 (точнее 4.5.2) не компилируется с:
Это я криво описал проблему. Сама библиотека под 4.5 и внутри неё FormattableString не поддерживаются, понятное дело.
А вот использующий библиотеку код вполне может быть с таргетом 4.6.
V>Т.е. разница не в 120 раз, а примерно в 6.
Угу. Результаты в стартовом топике под x64, у тебя x86, так?
Для более честного сценария надо [MethodImpl(MethodImplOptions.NoInlining)] на методы навесить, а то jit может заинлайнить вызов ассерта и вытащить строку за тело цикла (что он по-моему и делает). Тогда примерно то же, что у тебя получается.
А по факту главная проблема не в времени, а в избыточных аллокациях и тут надо во всех методах с params object[] args делать перегрузки с 1-2-3 аргументами.
Или просто писать код в стиле
if (!condition)
throw CodeExceptions.InvalidOperation($"Bad value {value};")
Остаётся ещё одна засада — с культурой, для дат и для для дробных чисел фигня выводится. И что самое обидное, я пока не знаю как её красиво решить даже для простого string.Format, который используется в CodeExceptions.
Re[3]: Interpolated strings: есть идеи, как подправить производител
Я понял в чем была проблема: это был Configuration = Debug, с запуском по Ctrl+F5.
С Configuration=Release, с запуском по Ctrl+F5, и в 4.6, и в 4.6.1. результат для String = 2-3ms.
Re[4]: Interpolated strings: есть идеи, как подправить производител
Здравствуйте, Venom, Вы писали:
V>У меня Any CPU. V>Еще в Project Properties->Build крыжик на "Prefer 32bit" стоит, который никак не отражен в .csproj, но возможно влияет.
Вот он и влияет. В Debug может быть собирается?
V>Я понял в чем была проблема: это был Configuration = Debug, с запуском по Ctrl+F5. V>С Configuration=Release, с запуском по Ctrl+F5, и в 4.6, и в 4.6.1. результат для String = 2-3ms.
Угадал)))
Здравствуйте, Sinix, Вы писали:
S>Как я понял, тогда был бы нужен костыль для случаев S>
S>var s = $"Hello, {Name}!";
S>
S>чтоб s был строкой.
Чтобы s был строкой и все было клево нужно всего-то вспомнить, что .NET — это как бы про ООП, и следовало запилить тип FormattableString как наследник System.String.
Хотя тут больше проблема не в типах, а в порядке вычисления. В ассертах мы имеем тот случай, когда необходима ленивость для вычисления ряда аргументов: форматной строки и всех ее параметров. Это в сущности фундаментальная проблема, так как CLR не предоставляет из коробки иных моделей вычисления кроме энергичной.
Здравствуйте, hardcase, Вы писали:
H>Чтобы s был строкой и все было клево нужно всего-то вспомнить, что .NET — это как бы про ООП, и следовало запилить тип FormattableString как наследник System.String.
Зануда mode: Liskov плачет и рыдает. Всё равно, что наследовать корову от молока
Если серьёзно — нету там хорошего решения. Более того, на практике if ... throw оказывается если и не удобнее, то уж точно не хуже. Сравни
Code.AssertState(
someLongCondition || someAnotherCondition || whatever,
$"Long {text} no one going to read bla-bla-bla and {so_on}.");
vs
if (!someLongCondition && !someAnotherCondition && !whatever)
throw CodeExceptions.InvalidOperation(
$"Long {text} no one going to read bla-bla-bla and {so_on}.")
Поэтому лично я просто использую второй вариант, как порождающий меньше всего WTF.
H>Хотя тут больше проблема не в типах, а в порядке вычисления.
Ну так не решит оно исходную проблему, перфоманс будет проседать из-за аллокации замыканий. Тут только code rewrite поможет. Ну, или старый-добрый if, что и быстрее, и проще.
Re[15]: Interpolated strings: есть идеи, как подправить прои
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, hardcase, Вы писали:
H>>Чтобы s был строкой и все было клево нужно всего-то вспомнить, что .NET — это как бы про ООП, и следовало запилить тип FormattableString как наследник System.String. S>Зануда mode: Liskov плачет и рыдает. Всё равно, что наследовать корову от молока
Это смотря как посмотреть. С точки зрения языка обе конструкции
$"..."
и
"..."
есть строки, вот только первая несколько более сложным образом вычисляется.
H>>Хотя тут больше проблема не в типах, а в порядке вычисления.
S>Ну так не решит оно исходную проблему, перфоманс будет проседать из-за аллокации замыканий.
Это если мыслить в нынешней принятой стратегии вычисления в CLR. Для эффективной реализации ассертов и логирования конструкцию
$""
следует рассматривать как ленивые вычисления — строка физически вычисляется ровно тогда, когда становится необходимым ее куда-то передать.
S>Если серьёзно — нету там хорошего решения. Более того, на практике if ... throw оказывается если и не удобнее, то уж точно не хуже. Сравни S>
S>Code.AssertState(
S> someLongCondition || someAnotherCondition || whatever,
S> $"Long {text} no one going to read bla-bla-bla and {so_on}.");
S>vs
S>if (!someLongCondition && !someAnotherCondition && !whatever)
S> throw CodeExceptions.InvalidOperation(
S> $"Long {text} no one going to read bla-bla-bla and {so_on}.")
S>
Вопрос первого или второго синтаксиса — это вопрос вкуса. Но принимая во внимание нынешнее положение дел, то вторая запись предпочтительнее. Здесь уместно вспомнить assert-макросы Nemerle, которые переписывают первый вариант во второй, и бакс-строки разворачиваются ровно когда они становятся необходимыми чтобы бросить исключение.
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Interpolated strings: есть идеи, как подправить производител
Здравствуйте, Sinix, Вы писали:
S>Code.AssertState(someCondition, "Message #{0}", 123); S>ну, т.е. обычная перегрузка и вариант с строкой форматирования. S>в 99.99% случаев ассерт не срабатывает, форматирование не требуется. S>Ну и как с этим жить?
Вынести ассерты на уровень языка? (как это сделано в D)
Re[2]: Interpolated strings: есть идеи, как подправить производител
Здравствуйте, Kolesiki, Вы писали:
K>Вынести ассерты на уровень языка? (как это сделано в D)
Не, сама по себе поддержка со стороны языка тут ничем не поможет, т.к. нужны произвольные типы исключений, поддержка вызова произвольных методов + выдача произвольных сообщений пользователю.
Т.е. возвращаемся к исходной проблеме.
Что будет без "произвольные типы исключений" и далее по списку — см на CodeContracts. Сама по себе идея шикарная, общий подход примерно тот же, что и в D, только вот на практике они неюзабельны абсолютно.