Reputation:
Please see the code below, in the last IF statement, I've tried different combinations of either "&&" or "||" but can only get a valid input in this example if both format booleans are set to true. Any other way I've tried writing the IF statement, either validation always returns error, or the validation rules stop applying.
private static readonly Regex regexSSNDashes = new Regex(@"^\d{3}[-]\d{2}[-]\d{4}$");
private static readonly Regex regexSSNNoDashes = new Regex(@"^\d{3}\d{2}\d{4}$");
public static string SSN(String propertyName, bool isRequired, bool allowDashFormat, bool allowNoDashFormat)
{
if ((String.IsNullOrWhiteSpace(propertyName))
&& (isRequired == true))
{
return "SSN required.";
}
if ((!String.IsNullOrEmpty(propertyName))
&& ((!regex.SSNDashes.IsMatch(propertyName)) && (allowDashFormat == true))
&& ((!regex.SSNNoDashes.IsMatch(propertyName)) && (allowNoDashFormat == true)))
{
return "Invalid SSN.";
}
return null;
}
Based on the answers and feedback below, here's the completed code which works wonderfully and is easily expandable by writing more Regex statements (I'll probably add EIN in the future) or write different strings to check for different phone formats are acceptable credit cards, etc.
using System;
using System.Text.RegularExpressions;
public class ValidationRules
{
// SSN Rules
// Format 123-45-6789
private static readonly Regex regexSSNDashes = new Regex(@"^\d{3}[-]\d{2}[-]\d{4}$");
// Format 123456789
private static readonly Regex regexSSNNoDashes = new Regex(@"^\d{3}\d{2}\d{4}$");
/// <summary>
/// Get error string if property is not in the specified formats.
/// </summary>
/// <param name="propertyName">The property being validated.</param>
/// <param name="isRequired">Bool value if the property is required to be filled else may be null</param>
/// <param name="allowDashFormat">Bool value if format 123-45-6789 is allowed.</param>
/// <param name="allowNoDashFormat">Bool value if format 123456789 is allowed.</param>
/// <returns>Returns custom string for error type specified if error exists, else returns null.</returns>
public static string SSN(String propertyName, bool isRequired,
bool allowDashFormat, bool allowNoDashFormat)
{
if (isRequired && String.IsNullOrWhiteSpace(propertyName))
{
return "SSN required.";
}
if (!String.IsNullOrEmpty(propertyName) &&
!(allowDashFormat && regexSSNDashes.IsMatch(propertyName)) &&
!(allowNoDashFormat && regexSSNNoDashes.IsMatch(propertyName)))
{
return "Invalid SSN.";
}
return null;
}
}
Upvotes: 1
Views: 78
Reputation: 1514
Try this. you should be good.
checking Boolean condition allowDashFormat
before checking regExMatch
improves the performance. as there is no need to check for regExMath if allowDashFormat is false.
public static string SSN(String propertyName, bool isRequired, bool allowDashFormat, bool allowNoDashFormat)
{
if ((String.IsNullOrWhiteSpace(propertyName))
&& (isRequired == true))
{
return "SSN required.";
}
if (!String.IsNullOrEmpty(propertyName)
&& (allowDashFormat && !regex.SSNDashes.IsMatch(propertyName)
&& (allowNoDashFormat && !regex.SSNNoDashes.IsMatch(propertyName))))
{
return "Invalid SSN.";
}
return null;
}
}
Upvotes: 0
Reputation: 521073
Your logic is off. It should be this:
if (String.IsNullOrWhiteSpace(propertyName) && isRequired)
{
return "SSN required.";
}
else if (!String.IsNullOrEmpty(propertyName) &&
!(allowDashFormat && regex.SSNDashes.IsMatch(propertyName)) &&
!(allowNoDashFormat && regex.SSNNoDashes.IsMatch(propertyName))
{
return "Invalid SSN.";
}
In plain English, this says that if the SSN is not null or empty and the input fails both regex patterns, depending on the dash mode, then the SSN is considered invalid.
The heart of the expression I wrote above is something called De Morgan's Law. It says that NOT(p OR q) == NOT p AND NOT q
.
Edit:
I would propose actually using a single regex pattern to cover both versions of acceptable social security numbers:
Regex bothSSNRegex = new Regex(@"^(?:\d{3}-\d{2}-\d{4})|(?:\d{7})$");
Upvotes: 1
Reputation: 11273
While the accepted answer is technically correct, let's ask which one is more maintainable, this one:
if (!String.IsNullOrEmpty(propertyName) &&
!(regex.SSNDashes.IsMatch(propertyName) && allowDashFormat) &&
!(regex.SSNNoDashes.IsMatch(propertyName) && allowNoDashFormat))
{
return "Invalid SSN.";
}
or this one:
//You've already checked for a null string, it doesn't need to be repeated here
if (allowDashFormat)
{
if (!regex.SSNDashes.IsMatch(propertyName))
return "Invalid SSN";
}
else
{
if (!regex.SSNNoDashes.IsMatch(propertyName))
return "Invalid SSN";
}
The point is not to make things complicated for the sake of making them short. The compiler will take care of that for you. Write maintainable/readable code, not short code.
Upvotes: 2