So here’s a question, what’s the difference between String.Format( string, object[]) and StringBuilder.AppendFormat( string, object[] ) ?
For those of you thate don’t know, String.Format allows you to parameterize your strings, by placing replacement tokens througout a string template. You can later fill in those tokens with parameterized data by passing it in as an array. Here is an example:
string.Format("I own a {0} and {1} name is '{2}'",
"cat", "her", "Ellie" );
Of course this would output the sentence: “I own a cat and her name is ‘Ellie'”. You can also achieve the same thing by calling StringBuilder.AppendFormat much like the following example:
StringBuilder sb = new StringBuilder();
sb.AppendFormat( "I own a {0} and {1} name is {2}",
"cat", "her", "Ellie" );
At first glance, you may be thinking that these are somewhat interchangable with the exception of performance. By now, we all know StringBuilder is usually faster for excessive string manipulation. What you may not know is that string.format calls the StringBuilder.AppendFormat method under the hood. Additionally, StringBuilder will throw an exception if the number of parameters does not match the number of tokens found in the template string. Try compiling and running a program that executes the following statement:
[STAThread]
static void Main(string[] args) {
string x = string.Format(
"{4} owns a {0} and {1} name is {2}.", "cat", "her", "Ellie" );
Console.WriteLine( x );
// For those of you that know WriteLine takes format strings... shhhhh
// I'm trying to make a point here!
}
You will receive the following exception.
An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll Additional information: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
This exception is actually thrown by StringBuilder.AppendFormat and the String.Format method bubbles the exception up without providing the consumer with any recourse if the parameters dont’ match up. However, if you call StringBuilder.AppendFormat yourself, you can place the code in a try catch block, and reap the benefits of a string that has been formatted as best as it can be with the parameters provided. Take the following code, for instance:
[STAThread]
static void Main(string[] args) {
StringBuilder sb = new StringBuilder();
try {
sb.AppendFormat( "{0} owns a {1} and {2} name is {3}.",
new object[] {"Tobin", "cat", "her"} );
}
catch(FormatException ex) {
Console.WriteLine("An exception occurred: {0}", ex.Message );
}
finally {
Console.WriteLine( sb.ToString() );
}
Console.ReadLine();
}
Notice here that we have caught the exception, reported on it, but can still write the string builder’s text to the screen — or at least the part that was parsed.
Now here’s the questions I pose for all of you:
- Since you now know that you can bypass the token-count to parameter-count validation check by using StringBuilder, should you incorporate this into your applications in instances where you don’t know how many parameters you are going to have?
- Would you consider this to be a bug, or a reasonable feature and why?