Versatile string validation in C#












2












$begingroup$


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.










share|improve this question









$endgroup$

















    2












    $begingroup$


    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.










    share|improve this question









    $endgroup$















      2












      2








      2


      1



      $begingroup$


      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.










      share|improve this question









      $endgroup$




      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.







      c# validation






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 1 hour ago









      Ehouarn PerretEhouarn Perret

      21719




      21719






















          3 Answers
          3






          active

          oldest

          votes


















          2












          $begingroup$

          Not much to say about the extensions methods, as they are mostly wrappers.



          However if you're looking for ways to make the algorithm more readable, LINQ is your friend. You can replace most of your logic with a one-liner:




          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;



          Like this:



          return str.All(c => c.IsHyphen() || c.IsLetterOrDigit()) && str.Count(c => c.IsHyphen()) <= 1;


          Which more clearly explains your intent, you can also move those expression to their separate methods to make it as readable as possible, this way you can keep adding new conditions, without modifying the existing logic (unless they interfere with one another that is).






          share|improve this answer









          $endgroup$





















            2












            $begingroup$


            • There's a bug: you're not checking if the last character is a letter or digit, only that it isn't a hyphen, so this fails to reject "abcdef&". Denis' solution may be less efficient (2 iterations instead of 1), but with at most 16 characters that's not much of a concern, and it's both easier to read and it works correctly.

            • The first two rules read very nicely. I especially like that the business rules are translated to code almost 1:1, that will make updating easier. However, I do think those extension methods are over-engineered. str.Length < 6 || str.Length > 16 and !char.IsLetter(str.First()) || str.Last() == '-' is already quite readable, and that doesn't require extra code that needs to be understood and maintained.

            • You can use => syntax for methods with single-expression bodies.






            share|improve this answer









            $endgroup$













            • $begingroup$
              I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
              $endgroup$
              – Denis
              10 mins ago










            • $begingroup$
              @Pieter Witvoet true, my bad, wrong copy and paste =/
              $endgroup$
              – Ehouarn Perret
              2 mins ago










            • $begingroup$
              It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
              $endgroup$
              – tinstaafl
              2 mins ago



















            1












            $begingroup$

            About versatility my thought is a separate class to stipulate the different possible rules:



            class ValidationRules
            {
            public const char HYPHEN = '-';
            public readonly int hyphenCount;
            public readonly bool needUpper;
            public readonly bool needLower;
            public readonly bool allowSpaces;
            public readonly int minLength;
            public readonly int maxLength;
            /// <summary>
            /// Constructor with min and max length and default rules:
            /// needUpper = true
            /// needLower = true
            /// allowSpaces = false
            /// hyphenCount = 1;
            public ValidationRules(int minLength, int maxLength)
            {
            this.minLength = minLength;
            this.maxLength = maxLength;
            hyphenCount = 1;
            needLower = true;
            needUpper = true;
            allowSpaces = false;
            }
            /// <summary>
            /// Constructor with supplied rules:
            public ValidationRules(int minLength, int maxLength, int hyphenCount, bool needUpper, bool needLower, bool allowSpaces)
            {
            this.minLength = minLength;
            this.maxLength = maxLength;
            this.hyphenCount = hyphenCount;
            this.needLower = needLower;
            this.needUpper = needUpper;
            this.allowSpaces = allowSpaces;
            }
            }


            the method to validate is still quite simple:



            /// <summary>
            /// Validate string according to validation rules
            /// </summary>
            /// <returns></returns>
            public static bool Validate(string input,ValidationRules rules)
            {
            if(input.Length < rules.minLength || input.Length > rules.maxLength)
            {
            return false;
            }
            if(!Char.IsLetter(input[0]) || input[input.Length-1] == ValidationRules.HYPHEN)
            {
            return false;
            }
            return input.Count(x => x =='-') <= rules.hyphenCount && input.All(x =>
            (rules.needUpper && char.IsUpper(x)) ||
            (rules.needLower && char.IsLower(x)) ||
            (rules.allowSpaces && char.IsWhiteSpace(x)) ||
            (x == ValidationRules.HYPHEN);
            }




            share









            $endgroup$













            • $begingroup$
              I like your approach!
              $endgroup$
              – Ehouarn Perret
              4 mins ago











            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212381%2fversatile-string-validation-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2












            $begingroup$

            Not much to say about the extensions methods, as they are mostly wrappers.



            However if you're looking for ways to make the algorithm more readable, LINQ is your friend. You can replace most of your logic with a one-liner:




            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;



            Like this:



            return str.All(c => c.IsHyphen() || c.IsLetterOrDigit()) && str.Count(c => c.IsHyphen()) <= 1;


            Which more clearly explains your intent, you can also move those expression to their separate methods to make it as readable as possible, this way you can keep adding new conditions, without modifying the existing logic (unless they interfere with one another that is).






            share|improve this answer









            $endgroup$


















              2












              $begingroup$

              Not much to say about the extensions methods, as they are mostly wrappers.



              However if you're looking for ways to make the algorithm more readable, LINQ is your friend. You can replace most of your logic with a one-liner:




              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;



              Like this:



              return str.All(c => c.IsHyphen() || c.IsLetterOrDigit()) && str.Count(c => c.IsHyphen()) <= 1;


              Which more clearly explains your intent, you can also move those expression to their separate methods to make it as readable as possible, this way you can keep adding new conditions, without modifying the existing logic (unless they interfere with one another that is).






              share|improve this answer









              $endgroup$
















                2












                2








                2





                $begingroup$

                Not much to say about the extensions methods, as they are mostly wrappers.



                However if you're looking for ways to make the algorithm more readable, LINQ is your friend. You can replace most of your logic with a one-liner:




                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;



                Like this:



                return str.All(c => c.IsHyphen() || c.IsLetterOrDigit()) && str.Count(c => c.IsHyphen()) <= 1;


                Which more clearly explains your intent, you can also move those expression to their separate methods to make it as readable as possible, this way you can keep adding new conditions, without modifying the existing logic (unless they interfere with one another that is).






                share|improve this answer









                $endgroup$



                Not much to say about the extensions methods, as they are mostly wrappers.



                However if you're looking for ways to make the algorithm more readable, LINQ is your friend. You can replace most of your logic with a one-liner:




                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;



                Like this:



                return str.All(c => c.IsHyphen() || c.IsLetterOrDigit()) && str.Count(c => c.IsHyphen()) <= 1;


                Which more clearly explains your intent, you can also move those expression to their separate methods to make it as readable as possible, this way you can keep adding new conditions, without modifying the existing logic (unless they interfere with one another that is).







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 48 mins ago









                DenisDenis

                6,28521755




                6,28521755

























                    2












                    $begingroup$


                    • There's a bug: you're not checking if the last character is a letter or digit, only that it isn't a hyphen, so this fails to reject "abcdef&". Denis' solution may be less efficient (2 iterations instead of 1), but with at most 16 characters that's not much of a concern, and it's both easier to read and it works correctly.

                    • The first two rules read very nicely. I especially like that the business rules are translated to code almost 1:1, that will make updating easier. However, I do think those extension methods are over-engineered. str.Length < 6 || str.Length > 16 and !char.IsLetter(str.First()) || str.Last() == '-' is already quite readable, and that doesn't require extra code that needs to be understood and maintained.

                    • You can use => syntax for methods with single-expression bodies.






                    share|improve this answer









                    $endgroup$













                    • $begingroup$
                      I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
                      $endgroup$
                      – Denis
                      10 mins ago










                    • $begingroup$
                      @Pieter Witvoet true, my bad, wrong copy and paste =/
                      $endgroup$
                      – Ehouarn Perret
                      2 mins ago










                    • $begingroup$
                      It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
                      $endgroup$
                      – tinstaafl
                      2 mins ago
















                    2












                    $begingroup$


                    • There's a bug: you're not checking if the last character is a letter or digit, only that it isn't a hyphen, so this fails to reject "abcdef&". Denis' solution may be less efficient (2 iterations instead of 1), but with at most 16 characters that's not much of a concern, and it's both easier to read and it works correctly.

                    • The first two rules read very nicely. I especially like that the business rules are translated to code almost 1:1, that will make updating easier. However, I do think those extension methods are over-engineered. str.Length < 6 || str.Length > 16 and !char.IsLetter(str.First()) || str.Last() == '-' is already quite readable, and that doesn't require extra code that needs to be understood and maintained.

                    • You can use => syntax for methods with single-expression bodies.






                    share|improve this answer









                    $endgroup$













                    • $begingroup$
                      I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
                      $endgroup$
                      – Denis
                      10 mins ago










                    • $begingroup$
                      @Pieter Witvoet true, my bad, wrong copy and paste =/
                      $endgroup$
                      – Ehouarn Perret
                      2 mins ago










                    • $begingroup$
                      It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
                      $endgroup$
                      – tinstaafl
                      2 mins ago














                    2












                    2








                    2





                    $begingroup$


                    • There's a bug: you're not checking if the last character is a letter or digit, only that it isn't a hyphen, so this fails to reject "abcdef&". Denis' solution may be less efficient (2 iterations instead of 1), but with at most 16 characters that's not much of a concern, and it's both easier to read and it works correctly.

                    • The first two rules read very nicely. I especially like that the business rules are translated to code almost 1:1, that will make updating easier. However, I do think those extension methods are over-engineered. str.Length < 6 || str.Length > 16 and !char.IsLetter(str.First()) || str.Last() == '-' is already quite readable, and that doesn't require extra code that needs to be understood and maintained.

                    • You can use => syntax for methods with single-expression bodies.






                    share|improve this answer









                    $endgroup$




                    • There's a bug: you're not checking if the last character is a letter or digit, only that it isn't a hyphen, so this fails to reject "abcdef&". Denis' solution may be less efficient (2 iterations instead of 1), but with at most 16 characters that's not much of a concern, and it's both easier to read and it works correctly.

                    • The first two rules read very nicely. I especially like that the business rules are translated to code almost 1:1, that will make updating easier. However, I do think those extension methods are over-engineered. str.Length < 6 || str.Length > 16 and !char.IsLetter(str.First()) || str.Last() == '-' is already quite readable, and that doesn't require extra code that needs to be understood and maintained.

                    • You can use => syntax for methods with single-expression bodies.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 22 mins ago









                    Pieter WitvoetPieter Witvoet

                    6,091826




                    6,091826












                    • $begingroup$
                      I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
                      $endgroup$
                      – Denis
                      10 mins ago










                    • $begingroup$
                      @Pieter Witvoet true, my bad, wrong copy and paste =/
                      $endgroup$
                      – Ehouarn Perret
                      2 mins ago










                    • $begingroup$
                      It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
                      $endgroup$
                      – tinstaafl
                      2 mins ago


















                    • $begingroup$
                      I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
                      $endgroup$
                      – Denis
                      10 mins ago










                    • $begingroup$
                      @Pieter Witvoet true, my bad, wrong copy and paste =/
                      $endgroup$
                      – Ehouarn Perret
                      2 mins ago










                    • $begingroup$
                      It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
                      $endgroup$
                      – tinstaafl
                      2 mins ago
















                    $begingroup$
                    I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
                    $endgroup$
                    – Denis
                    10 mins ago




                    $begingroup$
                    I agree on the extension methods part, another positive for using standard types and methods is that, experienced developers, know right away the way they function.
                    $endgroup$
                    – Denis
                    10 mins ago












                    $begingroup$
                    @Pieter Witvoet true, my bad, wrong copy and paste =/
                    $endgroup$
                    – Ehouarn Perret
                    2 mins ago




                    $begingroup$
                    @Pieter Witvoet true, my bad, wrong copy and paste =/
                    $endgroup$
                    – Ehouarn Perret
                    2 mins ago












                    $begingroup$
                    It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
                    $endgroup$
                    – tinstaafl
                    2 mins ago




                    $begingroup$
                    It seems to me that the loop will weed out any characters that aren't letters digits or hyphen
                    $endgroup$
                    – tinstaafl
                    2 mins ago











                    1












                    $begingroup$

                    About versatility my thought is a separate class to stipulate the different possible rules:



                    class ValidationRules
                    {
                    public const char HYPHEN = '-';
                    public readonly int hyphenCount;
                    public readonly bool needUpper;
                    public readonly bool needLower;
                    public readonly bool allowSpaces;
                    public readonly int minLength;
                    public readonly int maxLength;
                    /// <summary>
                    /// Constructor with min and max length and default rules:
                    /// needUpper = true
                    /// needLower = true
                    /// allowSpaces = false
                    /// hyphenCount = 1;
                    public ValidationRules(int minLength, int maxLength)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    hyphenCount = 1;
                    needLower = true;
                    needUpper = true;
                    allowSpaces = false;
                    }
                    /// <summary>
                    /// Constructor with supplied rules:
                    public ValidationRules(int minLength, int maxLength, int hyphenCount, bool needUpper, bool needLower, bool allowSpaces)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    this.hyphenCount = hyphenCount;
                    this.needLower = needLower;
                    this.needUpper = needUpper;
                    this.allowSpaces = allowSpaces;
                    }
                    }


                    the method to validate is still quite simple:



                    /// <summary>
                    /// Validate string according to validation rules
                    /// </summary>
                    /// <returns></returns>
                    public static bool Validate(string input,ValidationRules rules)
                    {
                    if(input.Length < rules.minLength || input.Length > rules.maxLength)
                    {
                    return false;
                    }
                    if(!Char.IsLetter(input[0]) || input[input.Length-1] == ValidationRules.HYPHEN)
                    {
                    return false;
                    }
                    return input.Count(x => x =='-') <= rules.hyphenCount && input.All(x =>
                    (rules.needUpper && char.IsUpper(x)) ||
                    (rules.needLower && char.IsLower(x)) ||
                    (rules.allowSpaces && char.IsWhiteSpace(x)) ||
                    (x == ValidationRules.HYPHEN);
                    }




                    share









                    $endgroup$













                    • $begingroup$
                      I like your approach!
                      $endgroup$
                      – Ehouarn Perret
                      4 mins ago
















                    1












                    $begingroup$

                    About versatility my thought is a separate class to stipulate the different possible rules:



                    class ValidationRules
                    {
                    public const char HYPHEN = '-';
                    public readonly int hyphenCount;
                    public readonly bool needUpper;
                    public readonly bool needLower;
                    public readonly bool allowSpaces;
                    public readonly int minLength;
                    public readonly int maxLength;
                    /// <summary>
                    /// Constructor with min and max length and default rules:
                    /// needUpper = true
                    /// needLower = true
                    /// allowSpaces = false
                    /// hyphenCount = 1;
                    public ValidationRules(int minLength, int maxLength)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    hyphenCount = 1;
                    needLower = true;
                    needUpper = true;
                    allowSpaces = false;
                    }
                    /// <summary>
                    /// Constructor with supplied rules:
                    public ValidationRules(int minLength, int maxLength, int hyphenCount, bool needUpper, bool needLower, bool allowSpaces)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    this.hyphenCount = hyphenCount;
                    this.needLower = needLower;
                    this.needUpper = needUpper;
                    this.allowSpaces = allowSpaces;
                    }
                    }


                    the method to validate is still quite simple:



                    /// <summary>
                    /// Validate string according to validation rules
                    /// </summary>
                    /// <returns></returns>
                    public static bool Validate(string input,ValidationRules rules)
                    {
                    if(input.Length < rules.minLength || input.Length > rules.maxLength)
                    {
                    return false;
                    }
                    if(!Char.IsLetter(input[0]) || input[input.Length-1] == ValidationRules.HYPHEN)
                    {
                    return false;
                    }
                    return input.Count(x => x =='-') <= rules.hyphenCount && input.All(x =>
                    (rules.needUpper && char.IsUpper(x)) ||
                    (rules.needLower && char.IsLower(x)) ||
                    (rules.allowSpaces && char.IsWhiteSpace(x)) ||
                    (x == ValidationRules.HYPHEN);
                    }




                    share









                    $endgroup$













                    • $begingroup$
                      I like your approach!
                      $endgroup$
                      – Ehouarn Perret
                      4 mins ago














                    1












                    1








                    1





                    $begingroup$

                    About versatility my thought is a separate class to stipulate the different possible rules:



                    class ValidationRules
                    {
                    public const char HYPHEN = '-';
                    public readonly int hyphenCount;
                    public readonly bool needUpper;
                    public readonly bool needLower;
                    public readonly bool allowSpaces;
                    public readonly int minLength;
                    public readonly int maxLength;
                    /// <summary>
                    /// Constructor with min and max length and default rules:
                    /// needUpper = true
                    /// needLower = true
                    /// allowSpaces = false
                    /// hyphenCount = 1;
                    public ValidationRules(int minLength, int maxLength)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    hyphenCount = 1;
                    needLower = true;
                    needUpper = true;
                    allowSpaces = false;
                    }
                    /// <summary>
                    /// Constructor with supplied rules:
                    public ValidationRules(int minLength, int maxLength, int hyphenCount, bool needUpper, bool needLower, bool allowSpaces)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    this.hyphenCount = hyphenCount;
                    this.needLower = needLower;
                    this.needUpper = needUpper;
                    this.allowSpaces = allowSpaces;
                    }
                    }


                    the method to validate is still quite simple:



                    /// <summary>
                    /// Validate string according to validation rules
                    /// </summary>
                    /// <returns></returns>
                    public static bool Validate(string input,ValidationRules rules)
                    {
                    if(input.Length < rules.minLength || input.Length > rules.maxLength)
                    {
                    return false;
                    }
                    if(!Char.IsLetter(input[0]) || input[input.Length-1] == ValidationRules.HYPHEN)
                    {
                    return false;
                    }
                    return input.Count(x => x =='-') <= rules.hyphenCount && input.All(x =>
                    (rules.needUpper && char.IsUpper(x)) ||
                    (rules.needLower && char.IsLower(x)) ||
                    (rules.allowSpaces && char.IsWhiteSpace(x)) ||
                    (x == ValidationRules.HYPHEN);
                    }




                    share









                    $endgroup$



                    About versatility my thought is a separate class to stipulate the different possible rules:



                    class ValidationRules
                    {
                    public const char HYPHEN = '-';
                    public readonly int hyphenCount;
                    public readonly bool needUpper;
                    public readonly bool needLower;
                    public readonly bool allowSpaces;
                    public readonly int minLength;
                    public readonly int maxLength;
                    /// <summary>
                    /// Constructor with min and max length and default rules:
                    /// needUpper = true
                    /// needLower = true
                    /// allowSpaces = false
                    /// hyphenCount = 1;
                    public ValidationRules(int minLength, int maxLength)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    hyphenCount = 1;
                    needLower = true;
                    needUpper = true;
                    allowSpaces = false;
                    }
                    /// <summary>
                    /// Constructor with supplied rules:
                    public ValidationRules(int minLength, int maxLength, int hyphenCount, bool needUpper, bool needLower, bool allowSpaces)
                    {
                    this.minLength = minLength;
                    this.maxLength = maxLength;
                    this.hyphenCount = hyphenCount;
                    this.needLower = needLower;
                    this.needUpper = needUpper;
                    this.allowSpaces = allowSpaces;
                    }
                    }


                    the method to validate is still quite simple:



                    /// <summary>
                    /// Validate string according to validation rules
                    /// </summary>
                    /// <returns></returns>
                    public static bool Validate(string input,ValidationRules rules)
                    {
                    if(input.Length < rules.minLength || input.Length > rules.maxLength)
                    {
                    return false;
                    }
                    if(!Char.IsLetter(input[0]) || input[input.Length-1] == ValidationRules.HYPHEN)
                    {
                    return false;
                    }
                    return input.Count(x => x =='-') <= rules.hyphenCount && input.All(x =>
                    (rules.needUpper && char.IsUpper(x)) ||
                    (rules.needLower && char.IsLower(x)) ||
                    (rules.allowSpaces && char.IsWhiteSpace(x)) ||
                    (x == ValidationRules.HYPHEN);
                    }





                    share











                    share


                    share










                    answered 6 mins ago









                    tinstaafltinstaafl

                    6,7001928




                    6,7001928












                    • $begingroup$
                      I like your approach!
                      $endgroup$
                      – Ehouarn Perret
                      4 mins ago


















                    • $begingroup$
                      I like your approach!
                      $endgroup$
                      – Ehouarn Perret
                      4 mins ago
















                    $begingroup$
                    I like your approach!
                    $endgroup$
                    – Ehouarn Perret
                    4 mins ago




                    $begingroup$
                    I like your approach!
                    $endgroup$
                    – Ehouarn Perret
                    4 mins ago


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212381%2fversatile-string-validation-in-c%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Why is a white electrical wire connected to 2 black wires?

                    Waikiki

                    What are all the squawk codes?