internal static WildcardElement Create(string pattern, ref int patternIndex)
            {
                if (patternIndex >= pattern.Length)
                {
                    return(null);
                }

                switch (pattern[patternIndex])
                {
                case '*':
                    return(WildcardAsteriskElement.Create(pattern, ref patternIndex));

                case '?':
                    return(WildcardQuestionElement.Create(pattern, ref patternIndex));

                case '#':
                    return(WildcardSharpElement.Create(pattern, ref patternIndex));

                case '[':
                {
                    int             startIndex = patternIndex;
                    WildcardElement element    = WildcardRangeElement.Create(pattern, ref patternIndex);
                    if (element == null)
                    {
                        patternIndex = startIndex;
                        element      = WildcardStringElement.Create(pattern, ref patternIndex);
                    }

                    return(element);
                }

                default:
                    return(WildcardStringElement.Create(pattern, ref patternIndex));
                }
            }
            internal new static WildcardRangeElement Create(string pattern, ref int patternIndex)
            {
                patternIndex++;
                int patternLength = pattern.Length;

                bool negate = false;
                var  chars  = new HashSet <char>();

                if (patternIndex < patternLength && pattern[patternIndex] == '!')
                {
                    patternIndex++;
                    negate = true;
                }

                bool closed = false;

                while (patternIndex < patternLength)
                {
                    char ch = pattern[patternIndex];
                    switch (ch)
                    {
                    case ']':
                    {
                        patternIndex++;
                        closed = true;
                    }
                    break;

                    case '\\':
                    {
                        patternIndex++;

                        if (patternIndex < patternLength)
                        {
                            ch = pattern[patternIndex++];
                            if (!chars.Contains(ch))
                            {
                                chars.Add(ch);
                            }
                        }
                    }
                        continue;

                    default:
                    {
                        if (char.IsLetter(ch))
                        {
                            patternIndex++;

                            if (patternIndex + 1 < patternLength &&
                                pattern[patternIndex] == '-' &&
                                char.IsLetter(pattern[patternIndex + 1]))
                            {
                                patternIndex++;                                                 // -
                                char fromChar = ch;
                                char toChar   = pattern[patternIndex++];
                                for (char c = fromChar; c <= toChar; c++)
                                {
                                    if (!chars.Contains(c))
                                    {
                                        chars.Add(c);
                                    }
                                }
                            }
                            else
                            {
                                if (!chars.Contains(ch))
                                {
                                    chars.Add(ch);
                                }
                            }
                        }
                        else if (char.IsDigit(ch))
                        {
                            patternIndex++;

                            if (patternIndex + 1 < patternLength &&
                                pattern[patternIndex] == '-' &&
                                char.IsDigit(pattern[patternIndex + 1]))
                            {
                                patternIndex++;                                                 // -
                                char fromChar = ch;
                                char toChar   = pattern[patternIndex++];
                                for (char c = fromChar; c <= toChar; c++)
                                {
                                    if (!chars.Contains(c))
                                    {
                                        chars.Add(c);
                                    }
                                }
                            }
                            else
                            {
                                if (!chars.Contains(ch))
                                {
                                    chars.Add(ch);
                                }
                            }
                        }
                        else
                        {
                            patternIndex++;

                            if (!chars.Contains(ch))
                            {
                                chars.Add(ch);
                            }
                        }
                    }
                        continue;
                    }

                    break;
                }

                if (!closed || chars.Count == 0)
                {
                    return(null);
                }

                var element = new WildcardRangeElement();

                element.Negate = negate;
                element.Chars  = chars;
                element.Next   = WildcardElement.Create(pattern, ref patternIndex);

                return(element);
            }