-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
To avoid using a string parameter everywhere the value should be a string, but not any string, it would be useful to make a constrained version of a string, which only allows certain values.
The same thing would be true for primitive types like ints, doubles, etc.
People keep building CustomerId, AccountNumber, ZipCode, AddressLine, SSN, etc types, which are all basically constrained strings. It is definitely possible to work around this by creating types like this:
class CustomerId
{
readonly string _value;
public CustomerId(string value)
{
Validate(value);
_value = value;
}
private static void Validate(string value)
{
if (value.Length != 9)
{
throw new ArgumentOutOfRangeException(value, "CustomerId length must be 9.");
}
}
public override string ToString()
{
return _value;
}
public static implicit operator CustomerId(string value)
{
return new CustomerId(value);
}
public static implicit operator string(CustomerId cid)
{
return cid._value;
}
}And, of course generalize it into a ConstrainedString with a pure virtual Validate function.
However, it would be nice to have language support for this, as I see far too often people using strings when they don't accept any string. If we get language support for the concept, it would be easier to create domain types and get those checks compile-time, and not runtime.
Not sure of the best syntax, but one proposition would be to extend the generic syntax, like this:
class CustomerId<T> where T: string { s => s.Length == 9 }
{
} class AccountNumber<T> where T: string { s => IsValidAccountNumber(s) }
{
public static bool IsValidAccountNumber(string s) {
return (s % 11 == 0); // Arbitrary validation logic
}
}and, similarily with primitive types:
class Age<T> where T: int { i => i >= 0 && i < 130 }
{
} class AngleDeg<T> where T: double { d => d >= 0 && d <= 360 }
{
}Etc, etc. This would make the language richer, and, maybe more checks could be performed compile-time (Roslyn to the rescue).