Returning a string is a cheap operation - as mentioned, it is just a matter of returning 32 or 64 bits (4 or 8 bytes).
However, as Stephen Petrov points out, operations with line + are associated with creating a new line and can be a bit expensive. If you want to save performance and memory, I would suggest doing something like this:
static int i = 0; static void Main(string[] args) { while (Console.ReadLine() == "") { var pageSB = new StringBuilder(); foreach (var section in new[] { AddHeader(), AddContent(), AddFooter() }) for (int i = 0; i < section.Length; i++) pageSB.Append(section[i]); Console.Write(pageSB.ToString()); } } static StringBuilder AddHeader() { return new StringBuilder().Append("Hi ").AppendLine("World"); } static StringBuilder AddContent() { return new StringBuilder() .AppendFormat("This page has been viewed: {0} times\n", ++i); } static StringBuilder AddFooter() { return new StringBuilder().Append("Bye ").AppendLine("World"); }
Here we use StringBuilders to store a link to all the strings that we want to concatenate, and wait until the end before merging them. This will save a lot of unnecessary add-ons (which are compared with the memory and processor).
Of course, I doubt that you will actually see any need for this in practice - and if you do, I will spend some time exploring the union, etc., to help reduce the garbage created by all string collectors, and perhaps consider creating a custom "string holder" that is best suited for your purposes.
source share