I had to export a bunch of data in a CSV file. Turned out that at the receiving end the Perl script didn't want to eat my export. Luckily there is a standard for CSV files here and as strong Microsoft follower I adhere to the standards. Read up on RFC 4180 here.

To make life a little easier in getting all fields of my class String.Formatted the correct way I hammered down a CustomFormatter to format output according RFC4180. Your WriteLines can now look like this where the CsvFormatter takes care of adding double-quotes for the fields that matter:

<snip>
// boring code omitted
sww.WriteLine(
String.Format(
new CsvFormatter(),
@"{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}",
topic.id,
topic.title,
topic.description,
topic.createdBy,
topic.createdOn,
topic.lastModifiedBy,
topic.lastModifiedOn,
postitem.id,
postitem.title,
postitem.content,
postitem.createdByUserName,
postitem.createdDate,
postitem.replyToId)
);

</snip>

The code for the CsvFormatter is here:

public class CsvFormatter:IFormatProvider, ICustomFormatter
{
#region IFormatProvider Members
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
{
return this;
}
else
{
return null;
}
}

#endregion

#region ICustomFormatter Members

public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (arg == null)
{
return "";
}
string result = "";
if (format == null)
{
result = arg.ToString();
}
else
{
result = String.Format(format, arg); // this part is never tested...
}
char[] escapeChars = new char[] {'"','\n','\r', ',' };
if (result.IndexOfAny(escapeChars) > -1)
{
result = result.Replace("\"", "\"\"");
result = "\"" + result + "\"";
}

return result;
}

#endregion
}

Obvious more ingenious ways are possible especially if you need more flexibility but this one did the trick for me (and Google didn't bring me a quick answer).