Hi I'm Trying to make a simple code contract for a setter which states a DateTime Has to be at least fifteen years old.
If I do the validation in a member of the contract class the compiler yields
Contract class 'TypeValidation.CodeContract.CitizenContract' references member 'TypeValidation.CodeContract.CitizenContract.BeGreaterThanFiveTeenYearsOld(System.DateTime)' which is not part of the abstract class/interface being annotated.
My code is:
[ContractClass(typeof(CitizenContract))]
public interface ICitizen
{
int Age { get; set; }
DateTime BirtDate { get; set; }
string Name { get; set; }
}
[ContractClassFor(typeof(ICitizen))]
public class CitizenContract : ICitizen
{
public int Age
{
get { return default(int); }
set
{
Contract.Requires<ArgumentOutOfRangeException>(value > 15, "Age must be sixteen or greater.");
}
}
public DateTime BirtDate
{
get { return default(DateTime); }
set
{
Contract.Requires<ArgumentOutOfRangeException>(MoreThanFifTeenYearsOld(value), "The birthdate has to be a minimum of sixteen years old");
}
}
public string Name
{
get { return default(string); }
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrWhiteSpace(value), "Name Cant be null or empty.");
Contract.Requires<ArgumentOutOfRangeException>(value.Length >= 3 && value.Length <= 50, "Name has to have between three and fifty.");
}
}
bool MoreThanFifTeenYearsOld(DateTime dateToValidate)
{
if (dateToValidate == default(DateTime)) return false;
DateTime zeroTime = new DateTime(1, 1, 1);
var currentTime = DateTime.Now;
if (currentTime <= dateToValidate) return false;
TimeSpan span = currentTime - dateToValidate;
return ((zeroTime + span).Year - 1) >= 16;
}
}
I don't understand why it complains, can anyone explain why? Thanks in advance
You cannot add new members, because the contracts are evaluated on arbitrary instances of ICitizen
, not on instances of CitizenContract
, and those don't have that method. Because your method does not actually need the instance, you can make it static
. This is not enough to silence the error, but you can move the method to another class. Also, the method should be public
and [Pure]
:
public static class CitizenContractHelpers {
[Pure]
public static bool MoreThanFifTeenYearsOld(DateTime dateToValidate) {
…
}
}
Also, the contract class should be abstract
.
Read the manual at http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf, there is everything you needed to know.
This example is not a good use of Code Contracts, which should be used to find programming bugs. Validity of your contract depends on the environment DateTime.Now
, which the programmer usually does not control (the user can change time on his computer while using your application). So in this case a simple if-throw check in the implemenations would be better.