Search code examples
c#.netlazy-loadingcode-contracts

How can I use code contracts to check the value of a Lazy<T> without losing the advantages of lazy evaluation?


I have code that looks something like this:

public class Foo
{
    private readonly Lazy<string> lazyBar;

    public Foo()
    {
        lazyBar = new Lazy<string>(() => someExpression);
    }

    public string Bar
    {
        get { return lazyBar.Value; }
    }

    public void DoSomething()
    {
        Contract.Requires(Bar != null); // This evaluates Bar, but all I really require is that WHEN Bar is evaluated, it is not null.

        ...
    }
}

Now, every place DoSomething is called, we must also prove that Bar is not null. But won't checking for this eliminate the benefit of lazy evaluation? Additionally, aren't we supposed to avoid side-effects in our contracts?

Is it possible to prove that someExpression will not resolve to null, without evaluating it?


Solution

  • Code Contracts doesn't have enough insight into Lazy<T> in order to make the connection between the original lambda and the result you get back.

    What you really want to be able to state (for Lazy<T>) is that any contracts that hold about the lambda's return value also hold about the Value value, but meta-level contracts like this aren't possible at the moment.

    What you could do is move someExpression into a method and then have a Contract.Ensures that result != null. This will then warn you if this condition does not hold. You can then put an Invariant onto the result; lazyBar.Value != null. This will mean that it isn't actually lazy, but for your release code you can build with CC in ReleaseRequires mode and these types of check will be eliminated (having a read in the manual of the different 'levels' of contract enforcement is highly recommended!)