4

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?

Matthew
  • 28,056
  • 26
  • 104
  • 170
  • 2
    If you require the Bar property to have a value, aren't you implicitly saying that before `DoSomething` can be called, the lazy-ness have to be resolved to a real value? In other words, I don't understand what you're asking. Are you asking how `DoSomething` can require `Bar` to have a value, without resolving the lazy-ness of that property? – Lasse V. Karlsen Jul 29 '11 at 13:26
  • @Lasse: `Bar` must resolve to a real value, but it does not need to already be resolved before the method call. `Contract.Requires(Bar != null)` is just an example, of course this particular `Requires` will evaluate `lazyBar`. – Matthew Jul 29 '11 at 13:28
  • So then... what is your question exactly? I don't understand what you're asking for here. – Lasse V. Karlsen Jul 29 '11 at 13:29
  • @Lasse: Is it possible to prove that `someExpression` will not resolve to `null`, without evaluating it? I edited my question to clarify. – Matthew Jul 29 '11 at 13:31
  • No, it is not possible to prove that. This has nothing to do with C# or .NET however, you just can't prove what the outcome of calling code is until you call it, *in the general case*. You can of course make assumptions, or just document that the expression *must* never evaluate to `null`, and then assume it won't. – Lasse V. Karlsen Jul 29 '11 at 13:35

4 Answers4

3

After you edited in your comment in the code I can answer your question, but I don't think I'm answering the exact question lurking in the shadows here, you be the judge.

The only way to know what the property would resolve to if you read from it, is to actually read from it, evaluating the expression you constructed the underlying Lazy<T> field with.

Now, what you can do, is to check the underlying field to ask if it has been evaluated.

You can, in other words, do this:

if (lazyBar.IsValueCreated)
    ....

Now, whether that will work with a contract I'm not sure, but the following thing should allow you to check:

Contract.Requires(!lazyBar.IsValueCreated || lazyBar.Value != null);

Since I am not an expert on contracts, I don't know if the above code will be turned into an expression tree and evaluated either way.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • Maybe I'm misunderstanding code contracts--isn't the whole point to prove that outcome of calling code must fit certain criteria without executing it? I'm new to code contracts so I'm probably just making some silly misunderstanding, but I though that was the purpose of the static analyzer. – Matthew Jul 29 '11 at 13:49
  • For example, if `(A == foo)` implies `(B == bar)`, and you prove that `(A == foo)`, the static analyzer will know that `(B == bar)` without evaluating it. – Matthew Jul 29 '11 at 13:57
  • There is no way to prove what the outcome of calling code will be without calling it. You can add code contracts that guarantee that the code will crash if the outcome ever deviates from what was expected, but the *actual* outcome cannot be proven, this is the halting problem in disguise. Note, *again*, I'm talking in the general sense. You will have lots of cases where it *can* be proven, for *some specific code*. However, in this case, you're calling code through a delegate, code contracts in .NET won't be able to handle that. – Lasse V. Karlsen Jul 29 '11 at 13:58
  • 1
    How would you set up code contracts to prove that `A==foo` implies `B==bar`? – Lasse V. Karlsen Jul 29 '11 at 13:59
  • 1
    @Lasse: I think you're missing the point a bit here. CC isn't about proving portions of arbitrary code, but proving relations between the contracts on that code. CC lives in an ideal world where things like ThreadAbortException and other C# nuisances don't exist - it works solely on the contracts you give it :) – porges Aug 01 '11 at 03:38
  • 1
    @Lasse: the same way as in logic: `x implies y` is `!x || y`, so `A != foo || B == bar`. – porges Aug 01 '11 at 03:52
3

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!)

porges
  • 30,133
  • 4
  • 83
  • 114
0

I can't understand why this doesn't work (and it really doesn't):

public class Foo { private readonly Lazy lazyBar;

public Foo()
{
    lazyBar = new Lazy<string>(() => someExpression);
    Contract.Ensures(!lazyBar.IsValueCreated);
}

    [ContractInvariantMethod]
    private static void Invariant()
    {
        Contract.Invariant(!lazyBar.IsValueCreated || lazyBar.Value != null);
    }

public void DoSomething()
{
    Contract.Assume(lazyBar.IsValueCreated);
    lazyBar.Value.AccessSomeMethod; //Here Code Contracts detect "Possibly calling a method on a null reference"

    ...
}

}

Cesc
  • 21
  • 1
  • If you have a new question, please ask it by clicking the [Ask Question](http://stackoverflow.com/questions/ask) button. Include a link to this question if it helps provide context. - [From Review](/review/low-quality-posts/13231582) – tarzanbappa Aug 05 '16 at 02:52
  • Sure it is a new question? Now it works for me, and it is a Lazy approach (I declared the invariant as static, and it was the cause it didn't work). – Cesc Aug 05 '16 at 03:38
0

This partly depends on the type that you're dealing.

For example, types that inherit from ICollection will not be itterated over in order to evaluate such methods as Count().

In the case where ICollection is implimented, the Count() method is optimised to check the Count property.

If you simply want to check that your Lazy object has "something" inside I suggest using the Any() method available to us in the System.Linq namespace.

This will then only need to do a single MoveNext in the collection before being able to determine whether there is "anything" inside it.

Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162