Вам необходимо закрыть теги tbody , tr и td . Чтобы узнать больше о таблицах: https://www.w3schools.com/html/html_tables.asp
Определенный ответ должен прийти от команды дизайна компилятора. Но позвольте мне взять удар здесь ...
Если ваш вопрос, почему компилятор не включает это:
string s = "";
for( int i = 0; i < 100; i ++ )
s = string.Concat( s, i.ToString() );
в это:
StringBuilder sb = new StringBuilder();
for( int i = 0; i < 100; i++ )
sb.Append( i.ToString() );
string s = sb.ToString();
наиболее вероятный ответ состоит в том, что это не оптимизация . Это переписать код, который вводит новые конструкции, основанные на знаниях и намерении, что разработчик имеет - не компилятор.
Этот тип изменений потребует компилятора, чтобы иметь больше знания BCL, чем уместно. Что если завтра, может быть доступна еще одна оптимальная служба сборки строки? Должен ли компилятор использовать это?
Что, если ваши условия петли были более сложными , следует ли компилятор попытаться выполнить какой-то статический анализ, чтобы решить, будет ли результатом такого перезаписи по-прежнему функционально эквиваленту? Во многих отношениях это было бы как решение проблемы остановки .
Наконец, я не уверен, что во всех случаях это приведет к более быстрому выполнению кода. Существует затрата для создания конструкции StringBuilder
и изменением его внутреннего буфера в виде текста. На самом деле, стоимость добавления сильно привязана к размеру соединения строки, сколько существует, то, как выглядит давление памяти. Это вещи, которые компилятор не могут предсказать заранее.
Это ваша работа в качестве разработчика для записи хорошо выполняющего код. Компилятор может помочь только путем обеспечения определенного безопасного , инвариантных оптимизаций. Не переписать свой код для вас.
Две причины:
Вы можете предложить людям использовать правильные вызовы для своего приложения, но в какой-то момент ответственность за правильность его решения лежит на разработчику.
Редактировать: Что касается отсечки, у нас есть еще пара проблем:
Re Ваше решение, мне пришлось сделать настройку, чтобы увидеть его работать для меня - вместо вашего контента ETC / FSTAB я использовал этот контент с указанной вами темы форума:
none /cygdrive cygdrive binary,posix=0,user,noacl 0 0
Я использую установщик 4.0. 3 Я достаточно счастлив, что это работает для меня, но я не могу предложить причину, почему, не быть достаточно знакомым с FSTAB-синтаксисом и вариантами. Надеюсь, это добавляет что-то полезное для кого-то другого.
-121--2980901- Поскольку задание компилятора для генерации семантически правильного кода. Изменение вызовов string.concat
к завозам StringBuilder.Append
будет изменять семантику кода.
Ответ LBuskin отличный; мне нужно добавить пару вещей.
Во-первых, JScript.NET делает эту оптимизацию. JScript часто используется менее опытными программистами для задач, связанных с построением больших строк в циклах, таких как построение JSON-объектов, HTML-данных и так далее.
Поскольку эти программисты могут не знать о n-квадратичной стоимости наивного распределения строк, могут не знать о существовании строковых конструкторов и часто пишут код по этому паттерну, мы посчитали целесообразным поместить эту оптимизацию в JScript.NET.
Программисты на C#, как правило, больше знают о стоимости кода, который они пишут, и больше знают о существовании таких готовых частей, как StringBuilder, поэтому они меньше нуждаются в такой оптимизации. И что более фундаментально, философия дизайна C# заключается в том, что это язык "делай то, что я сказал" с минимумом "магии"; JScript - это язык "делай то, что я имею в виду", который делает все возможное, чтобы понять, как лучше всего обслужить тебя, даже если это означает иногда неправильные догадки. Обе философии справедливы и полезны.
Иногда она "идет другим путем". Сравните этот выбор с выбором, который мы делаем для включения строк. Включения строк на самом деле компилируются как создание словаря, содержащего строки, а не как серия сравнений строк. Эта оптимизация может быть плохой, может быть быстрее просто провести сравнение строк. Но здесь мы делаем предположение, что вы "имели в виду" переключатель, чтобы быть поиском таблицы, а не серией операторов "if" - если бы вы имели в виду серию операторов "if", вы могли бы легко написать это самостоятельно.
Для одного конкатенирования нескольких строк (например, a + b + c + d + e + f + g + h + i + j) вы действительно хотите, чтобы использовали String.Concat
IMO. Он имеет накладные расходы, связанные с построением массива для каждого вызова, но его преимущество заключается в том, что метод может вычислить точную длину результирующей строки до того, как ему понадобится выделить какую-либо память. StringBuilder.Append(a).Append(b)....
дает только одно значение за раз, поэтому конструктор не знает, сколько памяти нужно выделить.
Что касается выполнения этого в циклах - в этот момент добавлена новая локальная переменная, и нужно добавить код для записи обратно в строковую переменную в нужное время (вызов StringBuilder.ToString()
). Что происходит при запуске в отладчике? Не будет ли непонятно, если не увидеть, как строится значение, становящееся видимым только в конце цикла? О, и конечно, вы должны выполнить соответствующую проверку, что значение не используется ни в одной точке до конца цикла...
Я считаю, что это будет немного сложнее для писателей компилятора. И когда вы ссылаетесь на промежуточные строки внутри петлей, помимо конкатенации (например, передача их в некоторые другие методы или около того), эта оптимизация не будет возможна.
Строка представляет собой неизменяемый тип, поэтому использование объединения строки медленнее, чем использование StringBuilder.Append
.
Редактировать: Чтобы уточнить мою точку немного больше, когда вы говорите о том, почему String.concat
не оптимизирован на StringBuilder.append
, StringBuilder
Класс имеет совершенно другую семантику к неизменному типу строки
. Почему вы должны ожидать, что компилятор оптимизирует, что, как они явно разные вещи? Кроме того, StringBuilder
- это музейный тип, который может динамически изменить его длину, зачем компилятор оптимизировать неизменяемый тип к смешанному типу? Это дизайн и семантика, уклоняемые в спецификации ECMA для .NET Framework, независимо от языка.
Это немного, как просить компилятора (и, возможно, ждать слишком много) для компиляции Char
и оптимизировать его в INT
, потому что int
работает на 32 бита вместо 8 битов и будет считаться быстрее!
Вероятно, потому что сложно сопоставить такой шаблон в коде, и в случае, если компилятор по какой-то причине не может выполнить сопоставление, производительность кода внезапно становится ужасной. Такая оптимизация кода будет способствовать написанию такого кода, что еще больше усилит негативное влияние в тех случаях, когда компилятор больше не может выполнять оптимизацию.
Для объединения известного набора строк StringBuilder
не быстрее, чем String.Concat
.