Attention members of the RegEx cult :) ... This solution is presented only as an example; no claim is made that this is any better coding technique than if one used RegEx. No claim is made that this is optimal code (performs faster, uses less memory) for a coded solution to this kind of parsing scenario. What this humble flea does claim, however, is that:
a. using a given coding problem to create small tools that you'll be likely to re-use in the future is a good idea.
b. for some people, like this humble flea, who is not such a RegEx expert, it is possible that code where the solution is inherently "visible," may be easier to maintain/modify ... for yourself, and others ... in the future.
Finally, lest ye judge, may I propose that seeing an example in code that illustrates what RegEx can
save you from coding may be useful to newcomers.
So, in the case you might find it interesting to see how such validation is handled in code, rather than with RegEx:
a. I'm always looking to build small tools when coding that can be re-used elsewhere (often putting them, later, as static extension methods, into a library .dll containing similar functions):
using System.Linq;
using System.Collections.Generic;
private const int MinYears = 16;
private const int MaxYears = 90;
private static bool AllAlpha(string test)
{
return ! test.Any(ch => ! Char.IsLetter(ch));
}
private static bool AllNumeric(string test)
{
return ! test.Any(ch => ! Char.IsDigit(ch));
}
private static bool IsYear(string year)
{
DateTime birthyeardate;
if(DateTime.TryParse(@"1/1/" + year, out birthyeardate))
{
int yearsold = DateTime.Now.Year - birthyeardate.Year;
if (yearsold >= MinYears && yearsold <= MaxYears) return true;
}
return false;
}
b. then, I might "sketch out" a method I'd like to use for implementation:
public bool TestStringSegments(string source, List<func><string,>> functions)
{
foreach (var func in functions)
{
if (!func(source)) return false;
}
return true;
}
List<func><string,>> DLValidateTests = new List<func><string,>>
{
str => AllAlpha(str.Substring(0,2)),
str => AllNumeric(str.Substring(2,2)),
str => IsYear(str.Substring(4,4)),
str => AllNumeric(str.Substring(8))
}; </func></func></func>
The idea here is to execute each Function in a List of Functions passed in as a parameter, where each Function in the List returns a boolean, and to return 'true only if all Functions return 'true. The 'foreach code is written in such a way that this function returns immediately when any "in the list" function it executes returns 'false.
Here's how this might be used in your case:
private void SomeButton_Click(object sender, EventArgs e)
{
bool validated1 = TestStringSegments("AB2219991234567", DLValidateTests);
bool validated2 = TestStringSegments("AB2220x51234567", DLValidateTests);
bool validated3 = TestStringSegments("AB2219191234567", DLValidateTests);
bool validated4 = TestStringSegments("A32219981234567", DLValidateTests);
}