I think I found a bug in the static contract checking tool. Is there a way besides tagging the whole thing with [ContractVerification(false)]
?
class Employee
{
public int? HierarchyLevel { get; private set; }
public Employee(int? level)
{
Contract.Requires<ArgumentException>(
(!level.HasValue)
||
level >= 0 && level <= 10);
Contract.Ensures(
(!HierarchyLevel.HasValue)
||
(HierarchyLevel.Value >= 0 && HierarchyLevel.Value <= 10));
this.HierarchyLevel = level; //unproven
// this doesnt work either
//if (!level.HasValue) {
// this.HierarchyLevel = new Nullable<int>();
//} else {
// this.HierarchyLevel = new Nullable<int>(level.Value);
//}
// can't even make the static checker shut up with that:
//Contract.Assume(
// (!HierarchyLevel.HasValue)
// ||
// (HierarchyLevel.Value >= 0 && HierarchyLevel.Value <= 10));
}
}
Surprisingly, The version below works. But I don't want to start writing unidiomatic code or introduce my own version of Nullable just to please the contract verification tool.
class Employee2
{
public int HierarchyLevel { get; private set; }
public bool HasLevel { get; private set; }
public Employee2(int level, bool hasLevel)
{
Contract.Requires<ArgumentException>(!hasLevel || level >= 0 && level <=10);
if (hasLevel) {
HasLevel = true;
HierarchyLevel = level;
} else {
HasLevel = false;
HierarchyLevel = -1;
}
}
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(
(!HasLevel) ||
(HierarchyLevel >= 0 && HierarchyLevel <= 10));
}
}