Reputation: 11344
I'm wondering whether it is possible to ensure (using code-contracts) that an iterator method will never yield a null item.
This simplified method:
public static IEnumerable<object> CreateSomeObjects()
{
Contract.Ensures(Contract.Result<IEnumerable<object>>() != null);
Contract.Ensures(Contract.ForAll(Contract.Result<IEnumerable<object>>(), _ => _ != null));
for (int i = 0; i < 10; ++i)
{
yield return new object();
}
}
Results in a compile time warning similar to this:
CodeContracts: MyClass.CreateSomeObjects()[0x9]: ensures unproven: Contract.ForAll(Contract.Result>(), _ => _ != null)
What can I do to prove it to the static checker?
Upvotes: 1
Views: 209
Reputation: 7238
Only way you can put contracts on iterators is:
public class Graph
{
public IEnumerable<Node> Nodes(Graph g)
{
Contract.Requires(g != null);
Contract.Ensures(Contract.ForAll(Contract.Result<IEnumerable<Nodei>>, node => node != null));
foreach (var x in g.MethodForGettingNodes())
yield return x;
}
}
The contracts above make sure that callers don’t pass in a null parameter, and the method itself guarantees that all elements in the resulting collection are non-null.
Currently, the static checker does not reason about collections and thus will not be able to prove the postcondition above.
According to documentation they still do not fix it since 2009, I had problems with cc 2 years ago, and they still did not fix it and i think they wont.
Upvotes: 1