How to Repeat a String in C#

August 23, 2022#Software Development
Article
Author image.

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
Method N Mean Error StdDev Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
RepeatLinq 1 15.575 ns 0.1010 ns 0.0844 ns 1.00 0.00 0.0025 - - 40 B
RepeatStrBuilder 1 17.407 ns 0.3854 ns 0.5885 ns 1.11 0.04 0.0071 - - 112 B
RepeatArray 1 9.459 ns 0.2053 ns 0.1920 ns 0.61 0.01 0.0041 - - 64 B
RepeatSpan 1 9.852 ns 0.2188 ns 0.3715 ns 0.63 0.03 0.0041 - - 64 B
RepeatLinq 10 71.550 ns 0.9862 ns 0.8742 ns 1.00 0.00 0.0081 - - 128 B
RepeatStrBuilder 10 52.637 ns 1.1027 ns 3.2515 ns 0.75 0.03 0.0142 - - 224 B
RepeatArray 10 40.338 ns 0.7593 ns 0.8744 ns 0.56 0.01 0.0112 - - 176 B
RepeatSpan 10 35.393 ns 0.7495 ns 0.7011 ns 0.49 0.01 0.0112 - - 176 B
RepeatLinq 100 554.149 ns 4.2416 ns 3.9676 ns 1.00 0.00 0.0420 - - 664 B
RepeatStrBuilder 100 274.108 ns 5.3881 ns 5.9889 ns 0.49 0.01 0.0825 - - 1296 B
RepeatArray 100 282.168 ns 4.4919 ns 4.2017 ns 0.51 0.01 0.0792 - - 1248 B
RepeatSpan 100 215.679 ns 3.8950 ns 3.6434 ns 0.39 0.01 0.0794 0.0002 - 1248 B
RepeatLinq 1000 5,296.572 ns 100.2936 ns 93.8147 ns 1.00 0.00 0.3815 0.0076 - 6064 B
RepeatStrBuilder 1000 2,477.808 ns 49.4452 ns 50.7766 ns 0.47 0.01 0.7668 0.0267 - 12096 B
RepeatArray 1000 2,755.265 ns 52.9493 ns 72.4775 ns 0.52 0.02 0.7668 0.0153 - 12048 B
RepeatSpan 1000 2,048.442 ns 39.6767 ns 55.6213 ns 0.39 0.01 0.7668 0.0153 - 12048 B

Copyright © 2022 NimblePros - All Rights Reserved