Introduction
I have known for a long time that you must have enough items in your parameter array to account for the highest index assigned to a format item. Today's discovery was that unused items in the list are completely harmless.
Clearly, the opposite case is false; an item with an index greater than the upper bound of the parameter array elicits a FormatException
exception.
Background
Format control strings are part of almost every .NET program, even the most trivial "Hello, World" program, because they are an implicit component of all but the most degenerate case of Console.Write()
and Console.WriteLine()
. Only the infrequently used overload that takes zero arguments works without one; for all others, it is a required argument. The same applies to all of its cousins, TextStrimg.WriteLine()
, string.Format()
, StringBuilder.AppendFormat()
, and so forth.
This leads to the subject of the parameter array. If your list has three or fewer items, you can dispense with formally defining an array, and just list them as the second, third, and fourth arguments. Nevertheless, internally, they constitute an array, if only an implicit one.
Using the Code
A short C# console program demonstrates all of the above points fairly well. Following is the entire program, all 89 lines of it, 50 of them comments, and another 14 that are completely blank, leaving a mere 25 of actual code. Of those 25, four define constants, one imports the System
namespace, and nine open or close scopes, leaving 12 to do something useful.
using System;
namespace FormatItemCountDemo
{
class Program
{
static void Main ( string [ ] pastrCmdLneArgs )
{
const string ANNOUNCE_1 = @" Total Format Items in Array = {0}";
const string ANNOUNCE_2 = @"{1} Total Format Items in Array = {0}";
const string ANNOUNCE_3 = @"{1} Total Format Items in Array = {0}{2}";
const string DUMMY_FORMAT_ITEM_2 = @" (Dummy Format Item 2, with leading space)";
int intNStrings = 0;
Console.WriteLine ( "Begin format item counting demonstration.\r\n" );
Console.WriteLine (
ANNOUNCE_1 ,
++intNStrings ,
Environment.NewLine );
Console.WriteLine (
ANNOUNCE_2 ,
++intNStrings ,
Environment.NewLine );
try
{
Console.WriteLine (
ANNOUNCE_3 ,
++intNStrings ,
Environment.NewLine );
}
catch ( FormatException errBadFormatControlString )
{
Console.WriteLine (
"{2}{0} exception{2}{2} Exception Message: {1}" ,
errBadFormatControlString.GetType ( ).FullName ,
errBadFormatControlString.Message ,
Environment.NewLine );
}
Console.WriteLine (
ANNOUNCE_3 ,
intNStrings ,
Environment.NewLine ,
DUMMY_FORMAT_ITEM_2 );
Console.WriteLine (
"{0}Done!{0}" ,
Environment.NewLine );
}
}
}
Create a new Console Program project in Visual Studio, paste everything shown above into it, and build. Set a breakpoint on the closing brace of the main routine if you want to see anything when it runs in the interactive debugger. Alternatively, after you build it, you can open a command prompt in the output directory, and execute the program, as I did to create the picture shown below.
Points of Interest
Most of the interesting bits are covered in the embedded comments. In case you aren't paying attention, the messages indicate the number of format items in the array; what they really convey is the minumum number of format items the array must contain to satisfy the format control string.
Apart from the discovery that motivated this article, one feature of the code that deserves attention is the way I comment the parameter arrays whenever I use Console
,WriteLine
, string.Format
, and others that format string
s.
Since the first two lines are printed from the same array, it is evident that the unused second item is completely ignored. Apart from wasting a few bytes, extra items in the array are completely harmless.
The third print statement is wrapped in a try
/catch
block, to prevent an unhandled exception from crashing the program. Following the exception report generated when the third print statement tries to execute, the fourth statement uses the same format control string, but it adds another item to the array of items. With three items, the array covers the format items in the format control string, and the print succeeds.
That's about all there is to it, apart from the fact that paring down the list of references to the bare essentials (System
), decreases the number of references from eight to three. The demonstration package is a complete Visual Studio solution, including both debug and release builds. As built, the assembly targets version 4.5 of the Microsoft .NET Framework, though it could certainly target any version of the framework, since it can hardly be said to push the envelope of Console.WriteLine
, which has been part of the framework since day 1.
History
- Sunday, 12th June 2016 saw the discovery of this quirk, creation of the demonstration program, and writing of this article
- Monday, 13th June 2016, I discovered and corrected two typographical errors.