Подумав об этом, я понял, что на самом деле хотел бы, чтобы String.Format () принимала IDictionary в качестве аргумента и чтобы шаблоны могли быть написаны с использованием имен вместо индексов.
Для подстановок строк с большим количеством возможных ключей / значений индексные номера приводят к неразборчивым шаблонам строк - и в некоторых случаях вы можете даже не знать, какие элементы будут иметь какое число, поэтому я придумал следующее расширение :
https://gist.github.com/896724
По сути, это позволяет вам использовать строковые шаблоны с именами вместо чисел и словарь вместо массива, а также иметь все другие полезные функции String.Format (), позволяющие при необходимости использовать пользовательский IFormatProvider. и позволяя использовать весь обычный синтаксис форматирования - точность, длина и т. д.
Пример , предоставленный в справочном материале для String.Format, является отличным примером того, как шаблоны со многими пронумерованными элементами становятся полностью неразборчивыми - портируя этот пример для использования этого нового метода расширения, вы получаете что-то вроде этого :
var replacements = new Dictionary<String, object>()
{
{ "date1", new DateTime(2009, 7, 1) },
{ "hiTime", new TimeSpan(14, 17, 32) },
{ "hiTemp", 62.1m },
{ "loTime", new TimeSpan(3, 16, 10) },
{ "loTemp", 54.8m }
};
var template =
"Temperature on {date1:d}:\n{hiTime,11}: {hiTemp} degrees (hi)\n{loTime,11}: {loTemp} degrees (lo)";
var result = template.Subtitute(replacements);
Как кто-то указал, если то, что вы пишете, должно быть сильно оптимизировано, не используйте что-то вроде этого - если вам нужно отформатировать миллионы строк таким образом, в цикле, накладные расходы памяти и производительности могут быть значительный.
С другой стороны, если вы беспокоитесь о написании разборчивого, обслуживаемого кода - и если вы выполняете, скажем, кучу операций с базой данных, в общей схеме, эта функция не добавит значительных накладных расходов. .
...
Для удобства я попытался добавить метод, который принимал бы анонимный объект вместо словаря:
public static String Substitute(this String template, object obj)
{
return Substitute(
template,
obj.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(obj, null))
);
}
По какой-то причине это не работает - передача анонимного объекта, такого как new { name: "value" }
этому методу расширения, выдает сообщение об ошибке во время компиляции, говорящее, что лучшим соответствием была версия IDictionary этого метода. Не уверен, как это исправить. (Кто?)