private IList <char> GetAlphaCharacters(AlphaCase alphaCase)
    {
        switch (alphaCase)
        {
        case AlphaCase.Lower:
            return(LowerAlphaChars);

        case AlphaCase.Upper:
            return(UpperAlphaChars);

        case AlphaCase.Both:
        default:
            return(new List <char>(LowerAlphaChars.Concat(UpperAlphaChars)));
        }
    }
    public string Generate(int length, int minNumeric = 0, int minAlpha = 0, AlphaCase alphaCase = AlphaCase.Both)
    {
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException("length");
        }
        if (minNumeric < 0)
        {
            throw new ArgumentOutOfRangeException("minNumeric");
        }
        if (minAlpha < 0)
        {
            throw new ArgumentOutOfRangeException("minAlpha");
        }
        if (length < minNumeric + minAlpha)
        {
            throw new ArgumentException();
        }
        if (length == 0)
        {
            return(string.Empty);
        }
        var result = new char[length];
        var index  = 0;

        foreach (var numeric in GenerateNumeric().Take(minNumeric))
        {
            result[index++] = numeric;
        }
        var alphaCharacters = GetAlphaCharacters(alphaCase);

        foreach (var alpha in Generate(alphaCharacters).Take(minAlpha))
        {
            result[index++] = alpha;
        }
        var restLength = length - index;

        if (restLength > 0)
        {
            var restCharacters = new List <char>(NumericChars.Concat(alphaCharacters));
            foreach (var rest in Generate(restCharacters).Take(restLength))
            {
                result[index++] = rest;
            }
        }
        // shuffle result
        return(new string(result.OrderBy(x => Rnd.Next()).ToArray()));
    }