The pure LINQ way of doing it is with the Aggregate
extension method:
public static string ToStringLinq<TKey, TValue> (this Dictionary<TKey, TValue> source, string keyValueSeparator, string sequenceSeparator)
{
return source.Aggregate(string.Empty, (acc, pair) => string.Format("{0}{1}{2}{3}{4}", acc, sequenceSeparator, pair.Key, keyValueSeparator, pair.Value));
}
The downside of the above method is that it will put a sequence separator at the start of your string.
Alternatively:
public static string ToStringLinq<TKey, TValue> (this Dictionary<TKey, TValue> source, string keyValueSeparator, string sequenceSeparator)
{
return source.Aggregate(string.Empty, (acc, pair) => string.Format("{0}{1}{2}{3}{4}", acc, pair.Key, keyValueSeparator, pair.Value, sequenceSeparator));
}
This will place a separator at the end instead of the beginning.
If it is important not to have a leading or trailing separator, you can certainly update the lambda to account for a case with an empty accumulator, or you could add code to seed with a string for the first element and then aggregate over the rest of the dictionary, as shown below:
public static string ToStringLinq<TKey, TValue> (this Dictionary<TKey, TValue> source, string keyValueSeparator, string sequenceSeparator)
{
var first = source.First();
var seed = string.Format("{0}{1}{2}", first.Key, keyValueSeparator, first.Value);
return source.Skip(1).Aggregate(seed, (acc, pair) => string.Format("{0}{1}{2}{3}{4}", acc, sequenceSeparator, pair.Key, keyValueSeparator, pair.Value));
}
Of course, this suffers the same problem of Mattias' answer, where it does more object creation as a result of the repeat string.Format
calls, but for situations where performance is not an issue, a single aggregate function call can be a very compact means of solving the problem.
throw new ArgumentException("Parameter can not be null.", "source")
\$\endgroup\$throw new ArgumentException("Parameter can not be null.", nameof(source));
\$\endgroup\$