Versatile string validation in C#
$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
Validatemethod, which accepts a string and returnstrueif it's valid andfalseif 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
$endgroup$
add a comment |
$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
Validatemethod, which accepts a string and returnstrueif it's valid andfalseif 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
$endgroup$
add a comment |
$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
Validatemethod, which accepts a string and returnstrueif it's valid andfalseif 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
$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
Validatemethod, which accepts a string and returnstrueif it's valid andfalseif 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
c# validation
asked 1 hour ago
Ehouarn PerretEhouarn Perret
21719
21719
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
$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).
$endgroup$
add a comment |
$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 > 16and!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.
$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
add a comment |
$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);
}
$endgroup$
$begingroup$
I like your approach!
$endgroup$
– Ehouarn Perret
4 mins ago
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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).
$endgroup$
add a comment |
$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).
$endgroup$
add a comment |
$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).
$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).
answered 48 mins ago
DenisDenis
6,28521755
6,28521755
add a comment |
add a comment |
$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 > 16and!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.
$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
add a comment |
$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 > 16and!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.
$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
add a comment |
$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 > 16and!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.
$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 > 16and!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.
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
add a comment |
$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
add a comment |
$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);
}
$endgroup$
$begingroup$
I like your approach!
$endgroup$
– Ehouarn Perret
4 mins ago
add a comment |
$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);
}
$endgroup$
$begingroup$
I like your approach!
$endgroup$
– Ehouarn Perret
4 mins ago
add a comment |
$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);
}
$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);
}
answered 6 mins ago
tinstaafltinstaafl
6,7001928
6,7001928
$begingroup$
I like your approach!
$endgroup$
– Ehouarn Perret
4 mins ago
add a comment |
$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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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