I passed a technical test the other day, one part included a cheap string validation and I am wondering this can be further improved to be more versatile to requirement changes.

The requirements were something like that 

> Create a `Validate` method, which accepts a string and returns `true` if it's valid and `false` if it's not.
> 
> A string is valid if it satisfies the rules below:
> 
> - The string must be at least 6 characters long and not exceed 16 characters.
> - The string must contain only letters, numbers and optionally one hyphen (-).
> - The string must start with a letter, and must not end with a hyphen.
> For example, `validate("Michelle Belle");` would return false because it contains a space.

My solution was like that:

    public static class ComparableExtensions
    {
        public static bool IsStrictlyLowerThan<TComparable>(this TComparable comparable, TComparable value)
            where TComparable : IComparable<TComparable>
        {
            return comparable.CompareTo(value) < 0;
        }

        public static bool IsStrictlyGreaterThan<TComparable>(this TComparable comparable, TComparable value)
            where TComparable : IComparable<TComparable>
        {
            return comparable.CompareTo(value) > 0;
        }
        
        public static bool IsStrictlyNotBetween<TComparable>(this TComparable comparable, TComparable lowerBound, TComparable upperBound)
            where TComparable : IComparable<TComparable>
        {
            if (lowerBound.IsStrictlyGreaterThan(upperBound))
            {
                throw new ArgumentOutOfRangeException(nameof(lowerBound) + nameof(upperBound));                
            }
            
            return comparable.IsStrictlyLowerThan(lowerBound) || comparable.IsStrictlyGreaterThan(upperBound);
        }
    }

    public static class CharExtensions
    {
        public static bool IsLetterOrDigit(this char c)
        {
            return char.IsLetterOrDigit(c);
        }
        
        public static bool IsLetter(this char c)
        {
            return char.IsLetter(c);
        }

        public static bool IsHyphen(this char c)
        {
            return c == '-';
        }
    }
    
    public class Test
    {
        public static bool Validate(string str)
        {
            if (str.Length.IsStrictlyNotBetween(6, 16))
            {
                return false;
            }

            if (!str.First().IsLetter() || str.Last().IsHyphen())
            {
                return false;
            }

            var hyphenCount = 0;

            for (var i = 1; i < str.Length - 1; i++)
            {
                if (str[i].IsLetterOrDigit())
                {
                    continue;
                }
                if (str[i].IsHyphen())
                {
                    hyphenCount++;
                    if (hyphenCount > 1)
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            
            return true;
        }
    }

I purposefully decided to not go with Regular Expressions to keep the logic readable and I am wondering if my code can be further refactored to incorporate new business rules.