G>Подавляющая часть использования стрингбилдера в прикладных программах — склейка массива строк в одну. Для этого есть string.Join и он даже чуть быстрее работает, чем цикл в билдере.
Это как, если там тоже билдер?
G>Для прикладной программы сейчас лучше использовать интерполяцию или string.join (ЧСХ оба внутри используют стрингбилдеры)
Здравствуйте, yenik, Вы писали:
G>>Подавляющая часть использования стрингбилдера в прикладных программах — склейка массива строк в одну. Для этого есть string.Join и он даже чуть быстрее работает, чем цикл в билдере. Y>Это как, если там тоже билдер?
Путаница получилась. string.Join(string[]) выделяет память один раз и копирует содержимое строк, string.Join(IEnumerable<string>) использует специализированный билдер если параметр не массив или List<string>.
G>>Для прикладной программы сейчас лучше использовать интерполяцию или string.join (ЧСХ оба внутри используют стрингбилдеры)
Y>Кстати, где посмотреть исходник String? https://source.dot.net/ же
Здравствуйте, gandjustas, Вы писали:
S>>Вот в С++ любят. И ведь приятнее же написать G>В C++ вообще любят извращения. S>>stringBuilder += "test" чем stringBuilder.Append("test") ? G>stringBuilder += "test" эьо stringBuilder = stringBuilder + "test", он должен возвращать новый объекти не изменять старый. Поэтому stringBuilder.Append
using System.Text;
var builder = new MyStringBuilder();
builder.Append("A");
builder.Append("B").Append("C");
builder += "D";
Console.WriteLine($"Builder is {builder}"); // Builder is ABCD
builder += "E" + builder + "F"; // And even…
Console.WriteLine($"Builder now is {builder}"); // Builder now is ABCDEABCDF
file class MyStringBuilder
{
private StringBuilder Builder { get; } = new StringBuilder();
public MyStringBuilder Append(string? value) {
Builder.Append(value);
return this;
}
public override string ToString() => Builder.ToString();
public static MyStringBuilder operator+(MyStringBuilder builder, string value) => builder.Append(value);
}
Описанная вами ниже "х + х + х" тут не случится, потому что речь об операторе сложения билдера и строки.
Это я к тому, что в отсутствии перегрузки оператора, кажется, нет ни технической ни даже логической проблем.
G>Да и в целом со стрингбилдером крайне редкий кейс, чтобы для него вводить такое в язык.
На сколько я знаю, в BCL вообще не переопределяют операторы там, где это не общеизвестно, типа арифметики. То есть вопрос не в редкости, а в принципиальном подходе. Что не мешает делать такое "для себя", потому что самому со своим DSL весьма не плохо можетб быть.
Help will always be given at Hogwarts to those who ask for it.
_
_FR>Можете конкретнее на проблему указать: вижу проблему в коде вида:
var a = sb + "test";
var b = sb + "test";
Результат будет крайне неочевидным. Профит неясен.
_FR>Это я к тому, что в отсутствии перегрузки оператора, кажется, нет ни технической ни даже логической проблем.
Конечно это проблема читаемости и семантики кода.
G>>Да и в целом со стрингбилдером крайне редкий кейс, чтобы для него вводить такое в язык.
_FR>На сколько я знаю, в BCL вообще не переопределяют операторы там, где это не общеизвестно, типа арифметики.
Например?
_FR>То есть вопрос не в редкости, а в принципиальном подходе. Что не мешает делать такое "для себя", потому что самому со своим DSL весьма не плохо можетб быть.
Мешает то, что код пишется для других людей, а не для себя или компилятора.
Здравствуйте, gandjustas, Вы писали:
_FR>>Можете конкретнее на проблему указать: вижу проблему в коде вида:
G>
G>var a = sb + "test";
G>var b = sb + "test";
G>
G>Результат будет крайне неочевидным. Профит неясен.
Это уже другое дело. "должен" в "должен возвращать новый объекти не изменять старый. Поэтому stringBuilder.Append" вызвало недоумение.
Касательно примера: а чего вы хотели добиться этим кодом? С тем же успехом можно утверждать, что
var str = "aaabbb";
str.Replace("a", "X");
str.Replace("b", "Y");
так же не очевиден Но, по сути, пример просто бессмысленен (как и ваш выше) для любого, кто знает, как работает string.
Бесмысслененым ваш пример кажется потому, что вы сохраняете в переменных ссылки на объект, ссылка на который у вас и так есть.
Просто интересно, можно ли увидеть понятный пример, где переопределённый "+" в стрингбилдере может вызвать недоумение.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, vaa, Вы писали:
S>>Вот в С++ любят. И ведь приятнее же написать S>>stringBuilder += "test" чем stringBuilder.Append("test") ? S>>Вроде бы и поддерживаются на уровне кода, но не пошло... Почему?
vaa>потому что есть string и интерполяция строк. в корке все это есть(+) и работает. vaa>билдер стоит рассматривать как низкоуровневый код(см реализацию интерполяции).
Можете объяснить, как "интерполяция строк" может заменить StringBuilder?
Ведь интерполляция строк — это же что-то связанное со строковыми литералами?
Читай, константами времени компиляции. А если требуется в рантайме собрать строку? Это уже "низкоуровневый код"?
Help will always be given at Hogwarts to those who ask for it.
S>>Вот в С++ любят. И ведь приятнее же написать
S>>stringBuilder += "test" чем stringBuilder.Append("test") ?
B>Писать — приятно, СОПРОВОЖДАТЬ ХРЕНОВО! B>Сидишь, в ус не дуешь, как вдруг:
B>
door += mochalka * kaktus;
Невыдуманные истории, о которых невозможно молчать.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, gandjustas, Вы писали:
_FR>>>Можете конкретнее на проблему указать: вижу проблему в коде вида:
G>>
G>>var a = sb + "test";
G>>var b = sb + "test";
G>>
G>>Результат будет крайне неочевидным. Профит неясен.
_FR>Это уже другое дело. "должен" в "должен возвращать новый объекти не изменять старый. Поэтому stringBuilder.Append" вызвало недоумение. _FR>Касательно примера: а чего вы хотели добиться этим кодом?
Это искусственный пример, демонстрирующий неочевидное поведение, которое никак не следует из того что написано.
В реальности будет не два раза test, а осмысленные строки.
_FR>так же не очевиден Но, по сути, пример просто бессмысленен (как и ваш выше) для любого, кто знает, как работает string.
Именно. Все знаю как работает string, в том числе то, что сложение строк не модифицирует аргументы.я даже больше скажу, нет ни одного типа ни в одной из популярных библиотек, где сложение модифицировали бы аргумент. И что-то мне кажется что это не только C# и .net касается
Поэтому реализация сложения с модификацией аргумента ошибочна с точки зрения понимания кода.
_FR>Бесмысслененым ваш пример кажется потому, что вы сохраняете в переменных ссылки на объект, ссылка на который у вас и так есть.
Это вы знаете как работает плюс, а я нет. Для меня сложение двух обьектов не модифицирует аргументы, поэтому результат надо сохранить в переменную.
_FR>Просто интересно, можно ли увидеть понятный пример, где переопределённый "+" в стрингбилдере может вызвать недоумение.
Пример выше. Любой код для понимания которого надо знать детали реализации — плохой.
Кстати string.Replace в этом плане как раз плохой в языке, где большинство объектов изменяемые. Если бы код, который игнорирует возвращаемое значение вызывал ошибку или ворнинг, было бы лучше. Но это поломали бы существующий код, поэтому не добавили. Хотя ворнинг могли бы.
Здравствуйте, Философ, Вы писали:
Ф>Здравствуйте, _FRED_, Вы писали:
Ф>Какой странный синтаксис. Почему нет main() и что это такое: _FR>>file class MyStringBuilder
Ф>? C# 11 file modifier
Здравствуйте, T4r4sB, Вы писали:
G>>Здравый смысл мешает. Что например должно вернуть выражение x + x + x, если плюс модифицирует первый аргумент?
TB>Вообще-то мы говорили про +=, а не про +
В C# составные операторы нельзя перегрузить, соотв. оператор "+=" будет выведен из оператора "+".
Здравствуйте, Baiker, Вы писали:
_>>Дык SB и есть тот самый "эффективный манипулятор строками", нет? Какую альтернативу ты ему видишь?
B>Что мешает внутри САМИХ СТРОК иметь тот "эффективный код" для сборки множества строк в одну??
Всё мешает, для формирования/модификации строки из множества строк нужен буфер(ы) изменяемого размера, желательно с возможность задания предполагаемого размера (capacity).
Строка в .NET неизменяемая (легально) и расположена в памяти непрерывным куском — эффективность при чтении.
Ранее, в .NET 2 точно, StringBuilder был похож на твою идеальную строку, имел один буфер, и когда при добавлении новой строки в нём не хватало места, ему приходилось создавать новый буфер с копированием в него содержимого старого, в текущей реализации (что в .NET 4+, что в Core) SB реализован в виде односвязного списка, и если при добавлении недостаточно места, то создаётся новый элемент списка.
B>У канпелятора МОРЕ инфы! Например, что строка конкатенируется в цикле. Или большом методе. Вот и подставляйте туда "эффективный код"!
У компилятора нет инфы доступной только в рантайме — предполагаемый размер формируемой строки, а для простых случаев есть string.Join.
Здравствуйте, gandjustas, Вы писали:
S>>>>stringBuilder += "test" чем stringBuilder.Append("test") ? G>>>stringBuilder += "test" эьо stringBuilder = stringBuilder + "test", он должен возвращать новый объекти не изменять старый.
fk0>> Кому должен? Что мешает вернуть референс на модифицированный старый?
G>Здравый смысл мешает. Что например должно вернуть выражение x + x + x, если плюс модифицирует первый аргумент?
Поэтому в C++ operator+= и operator+ -- две разные сущности. И одно это не другое. И в C# вроде же тоже.
Здравствуйте, pilgrim_, Вы писали:
_>Здравствуйте, Baiker, Вы писали:
_>>>Дык SB и есть тот самый "эффективный манипулятор строками", нет? Какую альтернативу ты ему видишь?
B>>Что мешает внутри САМИХ СТРОК иметь тот "эффективный код" для сборки множества строк в одну??
_>Всё мешает, для формирования/модификации строки из множества строк нужен буфер(ы) изменяемого размера
Каким боком меня, программиста, должно волновать наличие каких-то буферов?? Высокоуровневый ЯП для того и создаётся, чтобы НЕ ДУМАТЬ о низлежащих мелочах. Но мелкомягкие клоуны (вместо решения проблемы) просто шваркнули программистам "кусок системщины" в виде StringBuilder — типа "хотите скорость? ТРАХАЙТЕСЬ С НЕЙ САМИ!". Классическое решение MS не отягощать себя проблемами смертных.
В конце концов, они же сделали эффективную конкатенацию! Значит МОГЛИ, просто безалаберное руководство гнало количество фич в ущерб качеству. Именно поэтому C# достиг зрелости аж на 20-ый год жизни(!!!!!). А теперь посмотрите на Kotlin — язык почти идеально рождённый. Если б в нём всё делалось так же безобразно и медленно, как в C#, мы бы только через 20 лет о нём услышали!