Search code examples
c#drycode-contracts

Code Contracts chaining calls?


Basically I'm looking at 2 different situations:

Method calls within the same class:

public class MyClass
{
    public Bar GetDefaultBar(Foo foo)
    {
        Contract.Requires(foo != null);

        return GetSpecificBar(foo, String.Empty);
    }

    public Bar GetSpecificBar(Foo foo, string name)
    {
        Contract.Requires(foo != null);
        Contract.Requires(name != null);

        ...
    }
}

Method calls within different classes:

public class MyClass
{
    private MyBarProvider { get; set; }

    public Bar GetDefaultBar(Foo foo)
    {
        Contract.Requires(foo != null);

        return BarProvider.GetSpecificBar(foo, String.Empty);
    }

    //Object-Invariant ensures that MyBarProvider is never null...
}

public class MyBarProvider
{
    public Bar GetSpecificBar(Foo foo, string name)
    {
        Contract.Requires(foo != null);
        Contract.Requires(name != null);

        ...
    }
}

I'm wondering if it is necessary to have duplicate contracts for either of these situations? I'm guessing that there might be a way to avoid it in the first example (all within the same class), but not in the second example (different classes). Also, should I avoid duplicating or should it be in there?


Solution

  • I assume that the duplication you're talking about is Contract.Requires(foo != null);.

    You need to have that line in both methods, in both cases. If you don't include it in the caller, you'll get a "Requires unproven" at the call site, because the calling method's caller might pass a null value. If you don't include it in the callee, the callee's contract won't include the non-null requirement, and the contract analyzer will consider foo to be possibly null. That's because another call site would be free to pass in a null value.

    EDIT

    As Ɖiamond ǤeezeƦ points out, you can use the ContractAbbreviatorAttribute to refactor repetitive contract calls into a separate method. The attribute is not part of .NET Framework 4.0, but you can define it yourself. For more information, see Terje Sandstrom's blog post on reconciling code contracts null checks with FXCop: http://geekswithblogs.net/terje/archive/2010/10/14.aspx