1

Suppose you have an existing large project and you want to integrate Code Contracts in it. The existing code uses if-null-then-throw logic. For the given conditions, the documentation suggests to set the assembly mode to Custom Argument Validation.

I have the following classes:

class A
{
    protected virtual void Foo(int a, int b)
    {
        if (a == null)
            throw new ArgumentNullException(a);
        if (b == null)
            throw new ArgumentNullException(b);
        Contract.EndContractBlock();
    }
}
class B : A
{
    protected override void Foo (int a, int b)
    {
        // some stuff
        base.Foo(a, b);
    }
}

When I compile I get the following warning:

warning CC1055: Method 'B.Foo(int, int)' should contain custom argument validation for 'Requires(a != null)' as it overrides 'A.Foo(int,int)' which suggests it does. If you don't want to use custom argument validation in this assembly, change the assembly mode to 'Standard Contract Requires'.

I don't want to repeat the preconditions on every overridden method! Is there a way around it?

Roman Royter
  • 1,655
  • 13
  • 28
  • 2
    This is because you're using it in legacy mode, which won't inherit contracts. (Since in legacy code the contracts should be repeated anyway.) If you want automatic inheritance, you should use `Contract.Requires`. – porges May 28 '12 at 21:02
  • 1
    Exactly. Why should they be repeated? Why isn't the cccheck smart enough to identify the base method call and pick up the contract preconditions automatically? – Roman Royter May 29 '12 at 04:21
  • @RomanRoyter Sadly there does not seem to be a direct relation with "manual guards" and Requires or Requires .. it would be so much simpler if there were. – user2864740 Jan 08 '15 at 23:37

1 Answers1

4

It works fine if you use Contract.Requires() instead of Contract.EndContractBlock().

There is a section in the manual quoted below which suggests adding a [SuppressMessage] attribute to the method override.

From the Code Contracts user manual p.22 section 5.2.3.

Delegating Checks to Other Methods

Suppose you have a code pattern similar to the following code:

public class Base {
    public virtual void Compute(string data) {
    if (data == null) throw new ArgumentNullException(...);
        Contract.EndContractBlock();
        ...
    }
}

public class Derived : Base {
    public override void Compute(string data) {
        base.Compute(data);
        ...
    }
}

Then the tools will issue warning CC1055 with a message of the form:

Method ’Derived.Compute’ should contain custom argument validation for ' Requires (ArgumentNullException)(data ! = null)' as it overrides 'Base.Compute' which suggests it does.

In this situation, the warning is not helpful, as the implementation of Derived.Compute delegates the parameter validation to another method (in this case the base method). To avoid the warning in this situation without repeating the validation, you can add a SuppressMessage attribute to the method:

public class Derived : Base {
    [SuppressMessage("Microsoft.Contracts", "CC1055", Justification = "Validation performed in base method")]
    public override void Compute(string data) {
        base.Compute(data);
        ...
    }
}
shamp00
  • 11,106
  • 4
  • 38
  • 81