Ответ 1
От Atwood: Это. Просто. Не имеет. Материя.
У меня есть строка шаблона
это мой {0} шаблон {1} строка
который я планирую поместить в пользовательские значения при использовании String.Format()
.
Строка на самом деле длиннее, поэтому для удобства чтения я использую:
это моя строка {goodName1} {goodName2}
И затем String.Replace
каждый параметр со своим значением.
Как я могу получить максимальную производительность и удобство чтения?
Может быть, мне не нужно иметь этот шаблон в файле (как сейчас), но динамически строить его путем объединения в построитель строк и добавления параметров при необходимости? Хотя это менее читаемо.
Какие еще мои варианты?
От Atwood: Это. Просто. Не имеет. Материя.
Вы можете поместить параметры в словарь и использовать метод Regex.Replace
для замены всех параметров в одной замене. Таким образом, метод хорошо масштабируется, если строка шаблона становится длинной или число параметров увеличивается.
Пример:
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("goodName1", "asdf");
parameters.Add("goodName2", "qwerty");
string text = "this is my {goodName1} template {goodName2} string";
text = Regex.Replace(text, @"\{(.+?)\}", m => parameters[m.Groups[1].Value]);
Как и все, это зависит. Если код будет называться миллионы раз каждый день, подумайте о производительности. Если это несколько раз в день, тогда идите на удобочитаемость.
Я сделал некоторый бенчмаркинг между использованием обычных (неизменяемых) строк и StringBuilder. До тех пор, пока вы не начнете делать огромную сумму за небольшие промежутки времени, вам не нужно слишком беспокоиться об этом.
Мое спонтанное решение будет выглядеть так:
string data = "This is a {template1} that is {template2}.";
Dictionary<string, string> replacements = new Dictionary<string, string>(){
{"{template1}", "car"},
{"{template2}", "red"},
};
foreach (string key in replacements.Keys)
{
data = data.Replace(key, replacements[key]);
}
Console.WriteLine(data); // outputs "This is a car that is red."
Я использовал такие замены шаблонов в нескольких проектах реального мира и никогда не обнаружил, что это проблема производительности. Поскольку он прост в использовании и понимании, я не вижу причин сильно его менять.
ОСТОРОЖНО, чтобы увязнуть в этом типе мышления. Если этот код не работает сотни раз в минуту, а файл шаблона имеет размер несколько К, более важно сделать это. Не тратьте минутку на размышления о таких проблемах. В общем, если вы много работаете со строковыми манипуляциями, используйте конструктор строк. У него даже есть метод Replace. Но зачем беспокоиться. Когда вы закончите, и если вы обнаружите, что у вас проблема с производительностью, используйте PerfMon и устраните узкие места REAL в это время.
Самый быстрый способ сделать это - с помощью StringBuilder, используя индивидуальные вызовы StringBuilder.Append()
, например:
string result = new StringBuilder("this is my ")
.Append(UserVar1)
.Append(" template ")
.Append(UserVar2)
.Append(" string")
.ToString();
Я тщательно проверил код рамки, и это будет быстрее всего. Если вы хотите улучшить читаемость, вы можете сохранить отдельную строку, чтобы показать пользователя, и просто использовать это в фоновом режиме.
То же самое, что выше, чем Фредрик, выше, но с linq.
public static string FindandReplace(this string inputText, Dictionary<string, string> placeHolderValues)
{
if (!string.IsNullOrEmpty(inputText))
{
return placeHolderValues.Keys.Aggregate(inputText, (current, key) => current.Replace(key, placeHolderValues[key]));
}
else return inputText;
}
Если вам нужен хороший, быстрый, но простой механизм шаблонов, вы должны проверить StringTemplate. Для простых шаблонов, которые не требуют никакой логики или управления потоком в самом шаблоне, StringTemplate GREAT.
Просто изменил приведенный выше ответ на следующее:
string data = "This is a {template1} that is {template2}.";
Dictionary<string, string> replacements = new Dictionary<string, string>(){
{"{template1}", "car"},
{"{template2}", "red"},
};
data.Parse(replacements);
Метод расширения:
public static class Parser
{
public static string Parse(this string template, Dictionary<string, string> replacements)
{
if (replacements.Count > 0)
{
template = replacements.Keys
.Aggregate(template, (current, key) => current.Replace(key, replacements[key]));
}
return template;
}
}
Надеюсь, это поможет..:)