views:

6517

answers:

7

Hi,

What it's the best way to generate a string of \t's in C#

I am learning C# and experimenting with different ways of saying the same thing.

Tabs(uint t) is a function that returns a string with t amount of \t's

For example Tabs(3) returns "\t\t\t"

Which of these three ways of implementing Tabs(uint numTabs) is best?

Of course that depends on what "best" means.

  1. The LINQ version is only two lines, which is nice. But are the calls to Repeat and Aggregate unnecessarily time/resource consuming?

  2. The StringBuilder version is very clear but is the StringBuilder class somehow slower?

  3. The string version is basic, which means it is easy to understand.

  4. Does it not matter at all? Are they all equal?

These are all questions to help me get a better feel for C#.

private string Tabs(uint numTabs)
     {
         IEnumerable<string> tabs = Enumerable.Repeat(
                                      "\t", (int) numTabs);
         return (numTabs > 0) ? 
                 tabs.Aggregate((sum, next) => sum + next) : ""; 
     }  

private string Tabs(uint numTabs)
    {
        StringBuilder sb = new StringBuilder();
        for (uint i = 0; i < numTabs; i++)
            sb.Append("\t");

        return sb.ToString();
    }  

private string Tabs(uint numTabs)
    {
        string output = "";
        for (uint i = 0; i < numTabs; i++)
        {
            output += '\t';
        }
        return output; 
    }
+49  A: 

What about this:

string tabs = new String('\t', n);

Or better:

static string Tabs(int n)
{
    return new String('\t', n);
}
CMS
funny. I missed that, hehe. :-)
Alex Baranosky
+8  A: 

The best version is certainly to use the builtin way:

string Tabs(int len) { return new string('\t', len); }

Of the other solutions, prefer the easiest; only if this is proving too slow, strive for a more efficient solution.

If you use a StringBuilder and know its resulting length in advance, then also use an appropriate constructor, this is much more efficient because it means that only one time-consuming allocation takes place, and no unnecessary copying of data.

In your case:

StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
    sb.Append('\t');
return sb.ToString();
Konrad Rudolph
sb.Append('\t', len);
dangph
+3  A: 

Definitely don't do the last. Each time the loop runs, you are creating another string object in memory. Using this function multiple times on a dataset could lead you to OutOfMemory exceptions.

ck
+8  A: 

What about using extension method?


public static class StringExtensions
{
   public static string Repeat(this char chatToRepeat, int repeat) {

       return new string(chatToRepeat,repeat);
   }
   public  static string Repeat(this string stringToRepeat,int repeat)
   {
       var builder = new StringBuilder(repeat);
       for (int i = 0; i < repeat; i++) {
           builder.Append(stringToRepeat);
       }
       return builder.ToString();
   }
}


You could then write :

Debug.WriteLine('-'.Repeat(100)); // For Chars  
Debug.WriteLine("Hello".Repeat(100)); // For Strings

Note that a performance test of using the stringbuilder version for simple characters instead of strings gives you a major preformance penality : on my computer the difference in mesured performance is 1:20 between: Debug.WriteLine('-'.Repeat(1000000)) //char version and
Debug.WriteLine("-".Repeat(1000000)) //string version

Ronnie
+4  A: 

Well in all version of .NET to repeat a string you could always do this

public static string Repeat(string value, int count)
{
  return new StringBuilder().Insert(0, value, count).ToString();
}

for chars @CMS new String('\t', n) is your best bet.

Binoj Antony
A: 

The answer really depends on the complexity you want. For example, I want to outline all my indents with a vertical bar, so my indent string is determined as follows:

return new string(Enumerable.Range(0, indentSize*indent).Select(
  n => n%4 == 0 ? '|' : ' ').ToArray());
Dmitri Nesteruk
A: 

Extension methods:

    public static string Repeat(this string s, int n)
    {
        return new String(Enumerable.Range(0, n).SelectMany(x => s).ToArray());
    }

    public static string Repeat(this char c, int n)
    {
        return new String(c, n);
    }
Rodrick Chapman