4

I've got this code:

public class CodeContractSample
{
    private readonly List<object> _items = new List<object>();

    public IEnumerable<object> Query()
    {
        Contract.Ensures(Contract.Result<IEnumerable<object>>() != null);
        //if (_items == null) throw new Exception();
        return _items;
    }
}

CodeContracts gives this warning:

CodeContracts: ensures unproven: Contract.Result>() != null

If I uncomment the middle row it stops complaining. But why does it complain to start with? _items should never be null..?

Allrameest
  • 4,364
  • 2
  • 34
  • 50

4 Answers4

5

Contracts are not 100% and there are still gaps in what it understands.

You are right: there is no reason for the result being unproven. See http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/f82aa25c-e858-4809-bc21-0a08de260bf1 for more information on this specific issue.

For now, you can solve this using:

Contract.Assume(_items != null);

You can also achieve this using contract invariants:

[ContractInvariantMethod]
void Invariants()
{
    Contract.Invariant(_items != null);
}
Pieter van Ginkel
  • 29,160
  • 8
  • 71
  • 111
  • Nice, this is also useful after some of my Asserts in my unit tests... :) – Allrameest Jan 31 '11 at 15:16
  • 1
    It would be cleaner to solve it with an invariant, like this: `[ContractInvariantMethod] void Invariants() { Contract.Invariant(_items != null); }`. Otherwise, you need to Assume all over the place :) – porges Feb 01 '11 at 00:14
0

Why do you think items will never be null? You could have another method in that class that sets it to null ...

blowdart
  • 55,577
  • 12
  • 114
  • 149
0

Actually i can imagine this:

CodeContractSample s = new CodeContractSample();
s.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(s, null);
var q = s.Query();

What do You think ?

ZFE
  • 301
  • 2
  • 8
  • Yes, that could happen. But then the contract would throw an exception at runtime. When doing things with reflection I can no longer expect that the static compile-time checker would give me warnings. – Allrameest Feb 01 '11 at 13:57
-1

The Contract.Ensures line is making a promise that the method will never return null. But there is nothing in the code that prevents this until you uncomment the line.

Jack Allan
  • 14,554
  • 11
  • 45
  • 57
  • ...except that `_items` is initialised in the class the constructor and `Query` is a non-static method. – fearofawhackplanet Jan 31 '11 at 14:48
  • I don't think that kind of functionality has been implemented yet. It would require a change to the c# language. See http://channel9.msdn.com/Forums/TechOff/494357-Design-by-Contract-in-C/0ef9306b38314b1aa4c09deb0009144e – Jack Allan Jan 31 '11 at 14:54