Random string of variable length generator

Below is my code for generating a random string of random length. I am using it in integration tests. Currently I have almost 2000 tests running each time a commit is made to master and a few of those tests are using this class.

I would like to make sure the code is optimized so that the tests complete as quickly as possible.

public class Strings
{
    private static readonly Random Random = new Random();

    private static int RandomChar => Random.Next(char.MinValue, char.MaxValue);

    public static string GenerateRandomStringOfSetLength(int length)
    {
        return GenerateRandomString(length);
    }

    private static string GenerateRandomString(int length)
    {
        var stringBuilder = new StringBuilder();

        while (stringBuilder.Length - 1 <= length)
        {
            var character = Convert.ToChar(RandomChar);
            if (!char.IsControl(character))
            {
                stringBuilder.Append(character);
            }
        }

        return stringBuilder.ToString();
    }
}

Answer

Just two remarks:

  • RandomChar should be a method because it returns a different result each time – this is just a convention that we usually follow in C#

In general, methods represent actions and properties represent data. Properties are meant to be used like fields, meaning that properties should not be computationally complex or produce side effects.

from Choosing Between Properties and Methods

so

Do use a property, rather than a method, if the value of the property is stored in the process memory and the property would just provide access to the value.

but

Do use a method, rather than a property, in the following situations.

amonong many others:

  • The operation returns a different result each time it is called, even if the parameters do not change. For example, the NewGuid method returns a different value each time it is called.

  • You can cast the result to char and don’t need the Convert.ToChar

_

private static char RandomChar() => (char)Random.Next(char.MinValue, char.MaxValue);

You can also improve the performance by precalculating the array with chars:

private static readonly char[] Chars = 
    Enumerable
    .Range(char.MinValue, char.MaxValue)
    .Select(x => (char)x)
    .Where(c => !char.IsControl(c))
    .ToArray();

the RandomChar method would take the values from this array:

private static char RandomChar() => Chars[Random.Next(0, Chars.Length)];

so building the string can be a simple loop:

for (int i = 0; i < length; i++)
{
    stringBuilder.Append(RandomChar());
}

Without the StringBuilder this seems to be faster in tests by just ~8ms for 100.000 loops and a string lenght of 1.000

var chars = new char[length];
for (int i = 0; i < length; i++)
{
    chars[i] = RandomChar();
}
return new string(chars);

StringBuilder.ToString processes the data in order to build the string. It’s quite fast but in this particular situation the minimal overhead is noticable. Generally the StringBuilder is the fastet way to build strings so using it is definitely the right choice.


Changing the Random.Next(0, max) to Random.Next(max) improves the performance by another 10ms for the same tests.

Attribution
Source : Link , Question Author : Ebbs , Answer Author : t3chb0t

Leave a Comment