"Don't concatenate long strings," is generally solid advice in most languages. Due to internal representations, strings are frequently immutable and of a fixed length, so a block like this:
string s = getSomeString();
s = s + "some suffix";
creates three strings- the original, the suffix, and the third, concatenated string. Keep spamming instances, especially long ones, if you want to stress test your garbage collector.
While languages will do their best to optimize those kinds of operations, the general advice is to use string builders which can minimize those allocations and boost performance.
Or, you can do what Richard B's predecessor did, and abuse the heck out of string interpolation in C#.
StreamWriter sw = new StreamWriter(filename);
#region Export file header
string header = "";
header = "Title";
header = $"{header},\"First Name\"";
header = $"{header},\"Middle Name\"";
header = $"{header},\"Last Name\"";
header = $"{header},Suffix";
header = $"{header},Company";
header = $"{header},Department";
header = $"{header},\"Job Title\"";
header = $"{header},\"Business Street\"";
header = $"{header},\"Business Street 2\"";
header = $"{header},\"Business Street 3\"";
header = $"{header},\"Business City\"";
header = $"{header},\"Business State\"";
header = $"{header},\"Business Postal Code\"";
header = $"{header},\"Business Country/ Region\"";
header = $"{header},\"Home Street\"";
header = $"{header},\"Home Street 2\"";
header = $"{header},\"Home Street 3\"";
header = $"{header},\"Home City\"";
header = $"{header},\"Home State\"";
header = $"{header},\"Home Postal Code\"";
header = $"{header},\"Home Country/ Region\"";
header = $"{header},\"Other Street\"";
header = $"{header},\"Other Street 2\"";
header = $"{header},\"Other Street 3\"";
header = $"{header},\"Other City\"";
header = $"{header},\"Other State\"";
header = $"{header},\"Other Postal Code\"";
header = $"{header},\"Other Country/ Region\"";
header = $"{header},\"Assistant's Phone\"";
header = $"{header},\"Business Fax\"";
header = $"{header},\"Business Phone\"";
header = $"{header},\"Business Phone 2\"";
header = $"{header},Callback";
header = $"{header},\"Car Phone\"";
header = $"{header},\"Company Main Phone\"";
header = $"{header},\"Home Fax\"";
header = $"{header},\"Home Phone\"";
header = $"{header},\"Home Phone 2\"";
header = $"{header},ISDN";
header = $"{header},\"Mobile Phone\"";
header = $"{header},\"Other Fax\"";
header = $"{header},\"Other Phone\"";
header = $"{header},Pager";
header = $"{header},\"Primary Phone\"";
header = $"{header},\"Radio Phone\"";
header = $"{header},\"TTY/TDD Phone\"";
header = $"{header},Telex";
header = $"{header},Account";
header = $"{header},Anniversary";
header = $"{header},\"Assistant's Name\"";
header = $"{header},\"Billing Information\"";
header = $"{header},Birthday";
header = $"{header},\"Business Address PO Box\"";
header = $"{header},Categories";
header = $"{header},Children";
header = $"{header},\"Directory Server\"";
header = $"{header},\"E - mail Address\"";
header = $"{header},\"E - mail Type\"";
header = $"{header},\"E - mail Display Name\"";
header = $"{header},\"E-mail 2 Address\"";
header = $"{header},\"E - mail 2 Type\"";
header = $"{header},\"E - mail 2 Display Name\"";
header = $"{header},\"E-mail 3 Address\"";
header = $"{header},\"E - mail 3 Type\"";
header = $"{header},\"E - mail 3 Display Name\"";
header = $"{header},Gender";
header = $"{header},\"Government ID Number\"";
header = $"{header},Hobby";
header = $"{header},\"Home Address PO Box\"";
header = $"{header},Initials";
header = $"{header},\"Internet Free Busy\"";
header = $"{header},Keywords";
header = $"{header},Language";
header = $"{header},Location";
header = $"{header},\"Manager's Name\"";
header = $"{header},Mileage";
header = $"{header},Notes";
header = $"{header},\"Office Location\"";
header = $"{header},\"Organizational ID Number\"";
header = $"{header},\"Other Address PO Box\"";
header = $"{header},Priority";
header = $"{header},Private";
header = $"{header},Profession";
header = $"{header},\"Referred By\"";
header = $"{header},Sensitivity";
header = $"{header},Spouse";
header = $"{header},\"User 1\"";
header = $"{header},\"User 2\"";
header = $"{header},\"User 3\"";
header = $"{header},\"User 4\"";
header = $"{header},\"Web Page\"";
#endregion Export file header
sw.WriteLine(header);
The real killer to this is that there's no need for string concatenation at all. There's no reason one needs to WriteLine
the entire header at once. sw.Write("Title,");
Also, string interpolation is almost always more expensive than straight concatenation, and harder for compilers to optimize. I'm not about to benchmark this disaster to prove it, but I suspect this is going to be pretty much the most expensive option.
And don't worry, the same basic process follows for each individual row they're outputting:
string contactRow = "";
HtmlToText htmlToText = new HtmlToText();
bool extendedPropRetrieved = false;
#region Extract properties for export file
if (contact.CompleteName != null)
contactRow = $"\"{contact.CompleteName.Title}\""; // Title
else
contactRow = $"";
contactRow = $"{contactRow},\"{contact.GivenName}\""; // First name
contactRow = $"{contactRow},\"{contact.MiddleName}\""; // Middle name
contactRow = $"{contactRow},\"{contact.Surname}\""; // Last name
if (contact.CompleteName != null)
contactRow = $"{contactRow},\"{contact.CompleteName.Suffix}\""; //Suffix
else
contactRow = $"{contactRow},";
contactRow = $"{contactRow},\"{contact.CompanyName}\""; // Company
contactRow = $"{contactRow},\"{contact.Department}\""; // Department
contactRow = $"{contactRow},\"{contact.JobTitle}\""; // Job title
if (contact.PhysicalAddresses.Contains(PhysicalAddressKey.Business))
{
contactRow = $"{contactRow},\"{contact.PhysicalAddresses[PhysicalAddressKey.Business].Street}\""; // Business street
contactRow = $"{contactRow},"; // Business street 2
contactRow = $"{contactRow},"; // Business street 3
contactRow = $"{contactRow},\"{contact.PhysicalAddresses[PhysicalAddressKey.Business].City}\""; // Business city
contactRow = $"{contactRow},\"{contact.PhysicalAddresses[PhysicalAddressKey.Business].State}\""; // Business state
contactRow = $"{contactRow},\"{contact.PhysicalAddresses[PhysicalAddressKey.Business].PostalCode}\""; // Business postalcode
contactRow = $"{contactRow},\"{contact.PhysicalAddresses[PhysicalAddressKey.Business].CountryOrRegion}\""; // Business country/region
}
else
{
contactRow = $"{contactRow},";
contactRow = $"{contactRow},";
contactRow = $"{contactRow},";
contactRow = $"{contactRow},";
contactRow = $"{contactRow},";
contactRow = $"{contactRow},";
contactRow = $"{contactRow},";
}
// ... this goes on for about 600 lines
The physical address else
block is something really special, here.