Is there a way to String.Format
a message without having to specify {1}, {2},
etc? Is it possible to have some form of auto-increment? (Similar to plain old printf
)

- 41,555
- 36
- 141
- 182
-
What's the purpose of not using numbers? Maybe if we can follow the reason why you want to avoid using them, we assist with a more useful solution... – BenAlabaster Feb 18 '09 at 14:01
-
4I have about 20 parameters, and writing a number for each one is cumbersome. I'm also afraid I may miss a number, or use a number twice. And I feel that maintainability without numbers may be easier. – Hosam Aly Feb 18 '09 at 14:15
-
Understandable I suppose... I always find it laborious if I want to embed yet to be formatted strings into other yet to be formatted strings...and then append the params at the end of the process which also has the same drawbacks. – BenAlabaster Feb 18 '09 at 15:41
-
Using indices, you are not bound to the order of the supplied parameters. This is good when you want to translated that format string. – Hans Kesting Jul 05 '14 at 14:09
-
With C#7, answers are obsolete, as it includes ["string interpolation"](https://learn.microsoft.com/fr-fr/dotnet/csharp/language-reference/tokens/interpolated) as in Perl: `$"{name} is {age} year{(age == 1 ? "" : "s")} old."` --> *Horace is 34 years old*. – mins Mar 24 '19 at 10:55
7 Answers
Afraid not -- where would it put the objects into the string? Using printf, you still need to put specifiers in somewhere.

- 70,359
- 14
- 95
- 123
-
1Yes, I don't mind using specifiers, but I don't want to hard-code the indices. – Hosam Aly Feb 18 '09 at 14:02
-
@Hosam - is this for the purpose of embedding other formattable strings within formattable strings and then adding all the params at a later stage? – BenAlabaster Feb 18 '09 at 14:06
-
@balabaster: no, it's one call to `String.Format` to insert a few variables. – Hosam Aly Feb 18 '09 at 14:16
I think the best way would be passing the property names instead of Numbers. use this Method:
using System.Text.RegularExpressions;
using System.ComponentModel;
public static string StringWithParameter(string format, object args)
{
Regex r = new Regex(@"\{([A-Za-z0-9_]+)\}");
MatchCollection m = r.Matches(format);
var properties = TypeDescriptor.GetProperties(args);
foreach (Match item in m)
{
try
{
string propertyName = item.Groups[1].Value;
format = format.Replace(item.Value, properties[propertyName].GetValue(args).ToString());
}
catch
{
throw new FormatException("The string format is not valid");
}
}
return format;
}
Imagine you have a Student Class with properties like: Name, LastName, BirthDateYear and use it like:
Student S = new Student("Peter", "Griffin", 1960);
string str = StringWithParameter("{Name} {LastName} Born in {BithDate} Passed 4th grade", S);
and you'll get: Peter Griffin born in 1960 passed 4th grade.

- 3,162
- 2
- 32
- 36
If someone is interested, I have modified Ashkan's solution to be able to run it under WinRT:
/// <summary>
/// Formats the log entry.
/// /// Taken from:
/// http://stackoverflow.com/questions/561125/can-i-pass-parameters-to-string-format-without-specifying-numbers
/// and adapted to WINRT
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The arguments.</param>
/// <returns></returns>
/// <exception cref="System.FormatException">The string format is not valid</exception>
public static string FormatLogEntry(string format, object args)
{
Regex r = new Regex(@"\{([A-Za-z0-9_]+)\}");
MatchCollection m = r.Matches(format);
var properties = args.GetType().GetTypeInfo().DeclaredProperties;
foreach (Match item in m)
{
try
{
string propertyName = item.Groups[1].Value;
format = format.Replace(item.Value, properties.Where(p=>p.Name.Equals(propertyName))
.FirstOrDefault().GetValue(args).ToString());
}
catch
{
throw new FormatException("The string format is not valid");
}
}
return format;
}

- 41,555
- 36
- 141
- 182

- 150
- 1
- 7
One could always use this (untested) method, but I feel it's over complex:
public static string Format(char splitChar, string format,
params object[] args)
{
string splitStr = splitChar.ToString();
StringBuilder str = new StringBuilder(format + args.Length * 2);
for (int i = 0; i < str.Length; ++i)
{
if (str[i] == splitChar)
{
string index = "{" + i + "}";
str.Replace(splitStr, index, i, 1);
i += index.Length - 1;
}
}
return String.Format(str.ToString(), args);
}

- 41,555
- 36
- 141
- 182
I came up with this, again it's a bit cumbersome but it works fine for what I needed to do which was to pass a variable number or arguments to my own function in the same way as I'd use WriteLine. I hope it helps somebody
protected void execute(String sql, params object[] args)
{
for (int i = 0; i < args.Count(); i++ )
{
sql = sql.Replace(String.Format("{{{0}}}", i), args[i].ToString());
}
//...
}

- 61
- 1
- 2
-
could you please tell me in which program you have implemented that? I'd like to do some SQL injection. So to be honest you should really think about replacing this by using the [`SqlParameter`](http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.aspx) within the [`SqlCommand`](http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx) – Oliver Jan 24 '12 at 09:51