Pronounceable Name Generator I'm learning C# and have written a function which generates an easily-pronounceable fictional name by alternating between taking one vowel and one consonant. The one parameter, halfLength, will be the amount of vowels added and the amount of consonants added, meaning that the length of the returned string is double the given halfLength.

static string GeneratePronounceableName(int halfLength)
{
    char[] vowels = "aeiou".ToCharArray();
    char[] consonants = "bcdfghjklmnpqrstvwxyz".ToCharArray();
    List&lt;char&gt; chosenVowels = new List&lt;char&gt;();
    List&lt;char&gt; chosenConsonants = new List&lt;char&gt;();

    Random r = new Random();

    for (int i = 0; i &lt; halfLength; i++)
    {
        chosenVowels.Add(vowels[r.Next(0, 5)]);
        chosenConsonants.Add(consonants[r.Next(0, 21)]);
    }

    return string.Join("", chosenConsonants.Zip(chosenVowels, (v, c) =&gt; v.ToString() + c.ToString()));
}


Is there a way this can be made shorter, more idiomatic or more efficient?
int halfLength



Don't make the user think to much when specifying parameters if this can be avoided. Calculate the target length and let the user specify the length he needs.

If the name should always have an even length then you could check if the given one is odd and if so then add 1. 

length = length % 2 == 0 ? length : length + 1;


The loop just divides this by 2:

for (int i = 0; i &lt; length / 2; i++)


I do this because I assumed a longer string is better then a short one so I add 1 to odd lengths but this is actually not necessary as C# will round the number to the next lower int when dividing. This means that 5 / 2 == 2 as far as int division is concerned. If you're ok with shorter strings then you don't need the line with length + 1




char[] vowels = "aeiou".ToCharArray();
char[] consonants = "bcdfghjklmnpqrstvwxyz".ToCharArray();



You don't need to ToCharArray these because strings are already arrays. You can just define two constants:

const string vowels = "aeiou";
const string consonants = "bcdfghjklmnpqrstvwxyz";





List&lt;char&gt; chosenVowels = new List&lt;char&gt;();
List&lt;char&gt; chosenConsonants = new List&lt;char&gt;();



You don't need two lists that you join later. You can use the StringBuilder and create the name right away.




chosenVowels.Add(vowels[r.Next(0, 5)]);
chosenConsonants.Add(consonants[r.Next(0, 21)]);



Don't use magic numbers. Use the constants you have to get the length:




r.Next(0, 5)



You can use the overload that takes just the maxValue.




v.ToString() + c.ToString()



When building longer strings with lot's of concatenations use specialized methods or objects. Concatenating strings with the + operator is the slowest possible way to create a string. The StringBuilder is such an object. Highly optimized for string creation.



With all those optimizations the final result could look like this:

static string GeneratePronounceableName(int length)
{
    const string vowels = "aeiou";
    const string consonants = "bcdfghjklmnpqrstvwxyz";

    var rnd = new Random();
    var name = new StringBuilder();

    length = length % 2 == 0 ? length : length + 1;

    for (var i = 0; i &lt; length / 2; i++)
    {
        name
            .Append(vowels[rnd.Next(vowels.Length)])
            .Append(consonants[rnd.Next(consonants.Length)]);
    }

    return name.ToString();
}




Alternatively to the StringBuilder you could use in this example a char[] array and build the string yourself:

static string GeneratePronounceableName(int length)
{
    const string vowels = "aeiou";
    const string consonants = "bcdfghjklmnpqrstvwxyz";

    var rnd = new Random(); 

    length = length % 2 == 0 ? length : length + 1;

    var name = new char[length];

    for (var i = 0; i &lt; length; i += 2)
    {
        name[i] = vowels[rnd.Next(vowels.Length)];
        name[i+1] = consonants[rnd.Next(consonants.Length)];
    }

    return new string(name);
}