Как стать автором
Обновить

Комментарии 30

Молодец, хорошее исследование на тему boxing/unboxing. Насчет R# совет: его warning на redundant .ToString() call можно заменить на hint или suggestion. И видно, и глаз радуется зеленому индикатору.
Спасибо за совет, так и сделаю. Я ведь топик этот поэтому и написал, что мне не нравился желтый индикатор кода.
Спасибо за статью. Буду теперь везде юзать ToString().
Не, ну я понимаю, безударные гласные, одна/две буквы «н», даже ошибку в тся/ться я могу понять. Но откуда у людей в голове берется этот «ВЫЙГРЫШ» я понять не смогу никогда.
Наверное, оттуда, откуда и «руберойд» :)
Вообще, ToString() про перегруженых операциях лучще юзать почаще, т.к. его отсутствие временами порождает неочевидные(по крайней мере в первый раз, когда с этим сталкиваешься) неявные преобразования. Из наиболее известного:

string vals = «AAAAA»;
int val1 = 10;
int val2 = 11;
Console.WriteLine(vals[1] + val1 + ":" + val2); // Упс! :)

Console.WriteLine(vals[1].ToString() + val1 + ":" + val2); // Совсем другое дело.

Console.ReadLine();
По-моему этому учат ещё на первых курсах при упоминаниях string'ов — левая операнд задаёт тип результата:
  • string + int = string
  • int + int = int
  • int + string = error
левый операнд, конечно же
*slfx — сначала было «левая часть»…
И как тот факт, что char+int = int вписывается в вашу концепцию?

Вы код запускали ввобще?

>>int + string = error
string s = 12 + «qqq»; // No errors… Magic?

>>По-моему этому учат ещё на первых курсах

Мне кажется, вы не слишком на лекциях усердствовали :D
С моими лекциями и присутствием на них было всё в порядке. Спасибо, что поинтересовались.
Однако хотелось бы подчеркнуть что мой комментарий был реакцией на вполне конкретный пример. Чар и инт, собственно, там одно и то же. Смысл в написании код и понимании как он будет читаться (машиной). Я думаю ни для кого не секрет что у каждого выражения будет своё значение: 1 + «2» + 3 + 4, 1 + 2 + «3» + 4, 1 + 2 + 3 + «4», 1 + 2 + 3 + 4.

П.С.: магии нет — есть разные языки и их ревизии со своим отношением к explicit/implicit.
>>>Однако хотелось бы подчеркнуть что мой комментарий был реакцией на вполне конкретный пример.

Ну да, ну да… Я это сразу понял после вашего «int + string = error». :)

>>Чар и инт, собственно, там одно и то же.

Безусловно! Г-н Хейлсберг, всё время хотел у Вас спросить — отчего это разные типы?
Ну после Г-на Хейлсберг сразу стало всё понятно :3
Статья хорошая. Главный вывод из нее, как мне кажется — «используйте ToString() в тех случаях, когда это выгодно». А во всех остальных случаях я предпочту более компактный код.
главное ведь не то, насколько он компактный (иначе вы б не использовали «многословный» С#, а предпочли бы, к примеру, APL/J/K). главное насколько код удобочитаемый. для меня someInt + someString не настолько понятный код, как someInt.ToString() + someString (но это субъективно, конечно). а если, к тому же, более понятный код оказывается более эфективным, то я просто не вижу причин его использовать… (и только не нужно говорить, что набирать меньше. большинство проггеров на .ToString() тратят меньше секунды времени).
Всё относительно. Если есть узкое место, то его нужно оптимизировать, а добавлять во всех случаях, а не только для структур, вызов ToString() — это уже преждевременная оптимизация.

P.S. Кстати интересно, Resharper выдаёт предупреждение на код, находящийся в цикле, или на единичный вызов, или и там и там?
У меня выдавал на единичный вызов, но это как сказали выше настраивается.
Понятно, что настраивается. Просто интересно, если поместить тот же вызов в цикл, Resharper по умолчанию продолжит выдавать предупреждение или сочтёт что в цикле лучше оставить ToString()?
Да он всегда ругается, я когда писал примеры кода, точно помню, в цике он мне ToString() выделял серым и говорил, что его можно не вызывать.
а как тот факт, что вызов в цикле или нет может влиять на «суждения» решарпера? если даже это единичный вызов в методе, то сам метод может вызываться в цикле.
Сколько текста из-за обиды на решарпер :)
Но статья хороша, спасибо!
А при чем тут обида? Не нужно становиться заложником инструмента, вот и все. Нужно разбираться досконально в тех советах, что он предлагает. Решать, где совет обоснован, а где — не очень. Статья и призвана разобраться в одном из этих вопросов.
Использование ToSting() в скором времени приводит к тому, что он начинает плодиться по всему коду, и его вызывают просто на всякий случай, и это приводит к тому, что выигрыш, полученный в одном методе, тратится на 10 излишних вызовов в других (по крайней мере, в 80% код ревью, в которых приходилось участвовать, то было так).
Использование конкатенации (+ в С# или string.Concat) строк метод, имеющий право на жизнь, но я бы рекомендовал не использовать его как «волшебную палочку». Если реально код дожен быть более производительным — используйте StringBuilder. В той же книге Рихтера объясняется почему (вкратце, потому что этот класс по другому работает с массивом char). Например, немного модифицированный пример (чтобы строка постоянно росла).
var time = Stopwatch.StartNew();
string s = «habrahabr»;
for (int i = 0; i < 100000; i++)
{
s += i.ToString();
}
Console.WriteLine(time.Elapsed.ToString());
time = Stopwatch.StartNew();
StringBuilder sb = new StringBuilder();
sb.AppendFormat(«habrahabr»);
for (int i = 0; i < 100000; i++)
{
sb.Append(i);
}
Console.WriteLine(time.Elapsed.ToString());

дал следующие результаты:
00:01:10.4000846
00:00:00.0314729

Если не касаться производительности, то использование конкатенации здорово усложняет жизнь при локализации приложений.
ЗЫ. С темой упаковки/распаковки — поддерживаю автора на все сто
где-то читал конкатенация через +, дает выигрыш в сравнении со StringBuilder, если количество слагаемых не привышает 8, если элементов больше, то StringBuilder здесь лидер.
*превышает конечно же
Это точно, отладка тоже очень важный фактор… учитывая тот фактор, что заметная разнича только на миллионах и только с большими структурами, то лучше иметь красивый код в случае единичного использования или не очень большом цикле.
Автору спасибо, интересно было узнать :)
НЛО прилетело и опубликовало эту надпись здесь
Я запускал release версию, притом не из вижлы, а из командой строки, т.к. даже если вызывать через crtl+f5 программа выполняется стабильно медленнее.
Сначала не понял — R# это вроде как метапрограммистский проект на RSDN. Что касается решарпера, то да, у него есть ряд таких «коррекций», которые являются ошибочными. Например удаление пустого статического дефолтного конструктора.
Зачем нужен пустой static constructor?
Спасибо за статью, но…
Раньше тоже страдал такими вот «выигрышами» (да и сейчас нередко)… Но после плотной работы с оптимизацие производительности, понял, что такие выигрышы ничего не стоят. Даже самый «толстый» вызов стоит микросекунды, так что бороться здесь просто не за что. А если они становятся проблемой — значит проблема где-то выше.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации