How to Repeat a String in C#

August 23, 2022How to Repeat a String in C#
Philippe Vaillancourt

Philippe Vaillancourt, Senior Consultant

If you’re coming from another programming language like JavaScript, Rust or Go, you may be familiar with the repeat function found in the standard library of those languages. Unfortunately, C# doesn’t have this function - atleast as of .NET 6 - so we need to write our own. Here are some examples of how to repeat a string N times in C#.

Using LINQ

public static string RepeatLinq(this string text, uint n)
{
  return string.Concat(System.Linq.Enumerable.Repeat(text, (int)n));
}

Here we’re using the Enumerable.Repeat method from the System.Linq namespace to repeat the string n times. We then use the string.Concat method to concatenate the repeated strings together. This is a very simple way to repeat a string, but it’s not the most efficient way to do it.

Using StringBuilder

public static string RepeatStrBuilder(this string text, uint n)
{
  return new StringBuilder(text.Length * (int)n)
    .Insert(0, text, (int)n)
    .ToString();
}

For this one we instantiate a new StringBuilder object with the length of the string multiplied by the number of times we want to repeat it. Then we use the Insert method to insert the string n times into the StringBuilder, starting at the beginning of the string (index 0). Finally, we use the ToString method to return the string.

This method is generally more efficient than the previous one, is relatively simple and concise, but it’s still not the most efficient way to repeat a string.

Using a for loop over an Array of characters

public static string RepeatArray(this string text, uint n)
{
  var arr = new char[text.Length * (int)n];
  for (var i = 0; i < n; i++)
  {
    text.CopyTo(0, arr, i * text.Length, text.Length);
  }

  return new string(arr);
}

Ok, now things are getting interesting. We’re going to use a for loop to repeat the string n times. We’ll use a char[] array to store the repeated string. Then we’ll use the CopyTo method to copy the string into the array. This is a more complicated way of repeating a string, but it can be more effecient than the previous one, especially when n < 100. But we can do even better.

Using a for loop over a Span of characters

public static string Repeat(this string text, uint n)
{
  var textAsSpan = text.AsSpan();
  var span = new Span<char>(new char[textAsSpan.Length * (int)n]);
  for (var i = 0; i < n; i++)
  {
    textAsSpan.CopyTo(span.Slice((int)i * textAsSpan.Length, textAsSpan.Length));
  }

  return span.ToString();
}

Using a Span<char> we are dropping down a level of abstraction and essentially dealing with contiguous memory on the stack instead of strings. This is why this method is the most efficient of all the ones we’ve seen previously. We’re copying memory slices of the original string into the a new Span<char>. This turns out to be pretty efficient because it’s not allocating memory on the heap.

This is the method that we chose to use in the Ardalis.Extensions nuget package. You can see the source code on Github.

Here’s how easy it is to use the Repeat method. Go ahead and try it out!

Benchmarks

Here are the benchmark results of the different methods we’ve used to repeat a string.

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.22000
12th Gen Intel Core i9-12900K, 1 CPU, 24 logical and 16 physical cores
.NET Core SDK=6.0.303
  [Host]     : .NET Core 6.0.8 (CoreCLR 6.0.822.36306, CoreFX 6.0.822.36306), X64 RyuJIT
  DefaultJob : .NET Core 6.0.8 (CoreCLR 6.0.822.36306, CoreFX 6.0.822.36306), X64 RyuJIT
MethodNMeanErrorStdDevRatioRatioSDGen 0Gen 1Gen 2Allocated
RepeatLinq115.575 ns0.1010 ns0.0844 ns1.000.000.0025--40 B
RepeatStrBuilder117.407 ns0.3854 ns0.5885 ns1.110.040.0071--112 B
RepeatArray19.459 ns0.2053 ns0.1920 ns0.610.010.0041--64 B
RepeatSpan19.852 ns0.2188 ns0.3715 ns0.630.030.0041--64 B
RepeatLinq1071.550 ns0.9862 ns0.8742 ns1.000.000.0081--128 B
RepeatStrBuilder1052.637 ns1.1027 ns3.2515 ns0.750.030.0142--224 B
RepeatArray1040.338 ns0.7593 ns0.8744 ns0.560.010.0112--176 B
RepeatSpan1035.393 ns0.7495 ns0.7011 ns0.490.010.0112--176 B
RepeatLinq100554.149 ns4.2416 ns3.9676 ns1.000.000.0420--664 B
RepeatStrBuilder100274.108 ns5.3881 ns5.9889 ns0.490.010.0825--1296 B
RepeatArray100282.168 ns4.4919 ns4.2017 ns0.510.010.0792--1248 B
RepeatSpan100215.679 ns3.8950 ns3.6434 ns0.390.010.07940.0002-1248 B
RepeatLinq10005,296.572 ns100.2936 ns93.8147 ns1.000.000.38150.0076-6064 B
RepeatStrBuilder10002,477.808 ns49.4452 ns50.7766 ns0.470.010.76680.0267-12096 B
RepeatArray10002,755.265 ns52.9493 ns72.4775 ns0.520.020.76680.0153-12048 B
RepeatSpan10002,048.442 ns39.6767 ns55.6213 ns0.390.010.76680.0153-12048 B