Какой самый быстрый способ присоединить словарь <строка, строка> к строке запроса? - PullRequest
4 голосов
/ 05 августа 2009

У меня есть следующие данные:

Dictionary<string,string> dctParameters = new Dictionary(){
 {"a",var1},{"b",var2},{"c",var3},....
}

Я хочу объединить "dctParameters" в строку запроса.

Какой самый быстрый / лучший из следующих способов? Вы можете придумать лучший способ сделать это?

1-й метод:

StringBuilder data = new StringBuilder();
string result = dctParameters.Aggregate(data, (x, pair) => data.Append(pair.Key).Append("=").Append(pair.Value).Append("&")).ToString();

2-й метод:

StringBuilder data = new StringBuilder();
foreach (var item in dctParameters)
{
   data.Append(string.Format("{0}={1}&",item.Key, item.Value));
}
string result = data.ToString();

3-й метод:

StringBuilder data = new StringBuilder();
foreach (var item in dctParameters)
{
     data.Append(item.Key).Append("=").Append(item.Value).Append("&");
}
string result = data.ToString();

Ответы [ 10 ]

10 голосов
/ 05 августа 2009

Как насчет метода расширения как варианта предложения Эрика:

public static string ToQueryString(this Dictionary<string, string> dict)
{
    return '?' + string.Join("&", dict.Select(p => p.Key + '=' + p.Value).ToArray());
}

например:

dctParameters.ToQueryString();

Стоимость производительности любой из ваших реализаций действительно не стоит терять из-за того, что этот тип процесса вряд ли приведет к зависанию сервера. Проблема (как вы говорите) лучше не быстрее , и то, что вам нужно, это элегантный подход, а не наименьшее количество циклов ЦП.

7 голосов
/ 05 августа 2009

Предполагая , что, когда вы говорите «строка запроса», вы ссылаетесь на параметры, переданные в URL, тогда:

Как насчет:

String.Join("&", dic.Select(kv => kv.Key + "=" + kv.Value).ToArray());
6 голосов
/ 05 августа 2009

Если честно, мне кажется, что вы пытаетесь преждевременно оптимизировать.

Я не верю, что между ними будет существенная разница, но вы можете сравнить их с помощью таймеров. Поэтому я бы предложил выбрать тот, который, по вашему мнению, будет наиболее читабельным для других разработчиков, которым, возможно, потребуется поддерживать код.

1 голос
/ 05 августа 2009

Я принципиально согласен с Расс . Выберите наиболее читаемый и включите его в метод. Вы всегда можете изменить свою реализацию, если столкнетесь с проблемами производительности.

В качестве примечания вы, вероятно, получите больше производительности, если выберете другой класс для хранения ваших данных, поскольку перечисление довольно дорого. Подумайте о ListDictionary или даже KeyedCollection (для этого потребуется пользовательский Parameter класс или структура).

1 голос
/ 05 августа 2009

Все три метода неверны! Вы получите ложный амперсанд в самом конце.Это не повлияет на браузер, но это просто плохая форма.

Это, конечно, не тот, который включает string.Format, потому что это требует анализа вашей строки формата.Лично я пошел бы с третьим методом и предварительно вычислил бы общую длину конечной строки для подачи в конструктор StringBuilder.Даже если это примерно правильный размер или только предположил, вы не будете перераспределять память для StringBuilder.Попробуйте что-то вроде 20 для каждого элемента в вашем словаре, YMMV.

Другие делали и будут говорить о преждевременной оптимизации, но использование string.Format совершенно не нужно, не говоря уже о неправильном.

0 голосов
/ 06 августа 2009

Не берите в голову производительность, это не будет узким местом. Версия Эрика Смита, кажется, самая простая и чистая - продолжайте.

Но помните до UrlEncode значений, в противном случае у вас возникнет проблема, если значение содержит & или пробел или другие недопустимые символы.

0 голосов
/ 05 августа 2009

Если вам действительно нужна лучшая производительность (что кажется преждевременной оптимизацией), я думаю, что вы должны сначала рассчитать размер строки, а затем создать построитель строк с такой емкостью. Это предотвратит перераспределение строителя строк, а также приведет к появлению строки без неиспользуемого пространства:

int len = -1;
foreach (var item in dctParameters) {
   len += item.Key.Length + item.Value.Length + 2;
}
StringBuilder data = new StringBuilder(len);
foreach (var item in dctParameters) {
   if (data.Length > 0) data.Append('&');
   data.Append(item.Key).Append('=').Append(item.Value);
}
string result = data.ToString();
0 голосов
/ 05 августа 2009

3d, потому что он избегает форматирования (который является предварительной обработкой выражения формата) и в отличие от 1-го не использует избыточный вызов делегата

0 голосов
/ 05 августа 2009

В данном случае Best - это довольно относительный термин, поскольку все они делают то, что вы хотите. Что касается скорости, я не думаю, что стоит беспокоиться о нескольких миллисекундах здесь и там. Эти коллекции никогда не будут достаточно большими, чтобы вы могли заметить какие-либо заметные различия в производительности.

Сначала делайте то, что работает (без ущерба для хорошего дизайна), а затем беспокойтесь об оптимизации, когда вам нужно.

0 голосов
/ 05 августа 2009

Я думаю, ваш третий метод имеет наименьшие накладные расходы, но он может быть близок к вашему второму Я не знаю, что делает Append () под прикрытием или что делает String.Format.

Мне нравится, как выглядит ваш второй метод; это наиболее читабельно для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...