Code Contracts: Ensures Unproven & Requires Unproven

I'm not sure if I'm doing something wrong here or if it needs to be fixed...

I have a custom Dictionary wrapper class and here is a snippet of the code that is necessary.

public int Count
{
    get
    {
        Contract.Ensures(Contract.Result<int>() >= 0);

        return InternalDictionary.Count;
    }
}

public bool ContainsKey(TKey key)
{
    //This contract was suggested by the warning message, if I remove it
    //I still get the same warning...
    Contract.Ensures(!Contract.Result<bool>() || Count > 0);

    return InternalDictionary.ContainsKey(key);
}

The only reason I added the line for the ContainsKey is because I got the following warning message (and still do): Codecontracts: ensures unproven: !Contract.Result<bool>() || @this.Count > 0 Codecontracts: ensures unproven: !Contract.Result<bool>() || @this.Count > 0 . I can remove this line and still get the SAME ISSUE!

What do I do here to get rid of these issues?


Update:

I also tried (as suggested)...

public Boolean ContainsKey(TKey key)
{
    Contract.Requires(Count == 0 || InternalDictionary.ContainsKey(key));
    Contract.Ensures(!Contract.Result<bool>() || Count > 0);

    return InternalDictionary.ContainsKey(key);
}

Warning 5 Method 'My.Collections.Generic.ReadOnlyDictionary 2.ContainsKey(type parameter.TKey)' implements interface method 'System.Collections.Generic.IDictionary 2.ContainsKey(type parameter.TKey)', thus cannot add Requires.


"I have a custom Dictionary wrapper class" - that implements IDictionary<TKey, TValue> . Interface methods can specify contracts, and the class methods that implement them must meet the contracts. In this case, IDictionary<TKey, TValue>.ContainsKey(TKey) has the contract you're asking about:

Contract.Ensures(!Contract.Result<bool>() || this.Count > 0);

Logically, !a || b !a || b can be read as a ===> b ( a implies b ), and using that, we can translate this to English:

If ContainsKey() returns true, the dictionary must not be empty.

This is a perfectly sensible requirement. An empty dictionary must not claim to contain keys. This is what you need to prove.

Here's a sample DictionaryWrapper class that adds Contract.Ensures to promise that the implementation detail of Count being equal to innerDictionary.Count is a hard guarantee that other methods can rely upon. It adds a similar Contract.Ensures to ContainsKey so that the IDictionary<TKey, TValue>.TryGetValue contract is also verifiable.

public class DictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>
{
    IDictionary<TKey, TValue> innerDictionary;

    public DictionaryWrapper(IDictionary<TKey, TValue> innerDictionary)
    {
        Contract.Requires<ArgumentNullException>(innerDictionary != null);
        this.innerDictionary = innerDictionary;
    }

    [ContractInvariantMethod]
    private void Invariant()
    {
        Contract.Invariant(innerDictionary != null);
    }

    public void Add(TKey key, TValue value)
    {
        innerDictionary.Add(key, value);
    }

    public bool ContainsKey(TKey key)
    {
        Contract.Ensures(Contract.Result<bool>() == innerDictionary.ContainsKey(key));
        return innerDictionary.ContainsKey(key);
    }

    public ICollection<TKey> Keys
    {
        get
        {
            return innerDictionary.Keys;
        }
    }

    public bool Remove(TKey key)
    {
        return innerDictionary.Remove(key);
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return innerDictionary.TryGetValue(key, out value);
    }

    public ICollection<TValue> Values
    {
        get
        {
            return innerDictionary.Values;
        }
    }

    public TValue this[TKey key]
    {
        get
        {
            return innerDictionary[key];
        }
        set
        {
            innerDictionary[key] = value;
        }
    }

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        innerDictionary.Add(item);
    }

    public void Clear()
    {
        innerDictionary.Clear();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return innerDictionary.Contains(item);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        innerDictionary.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get
        {
            Contract.Ensures(Contract.Result<int>() == innerDictionary.Count);
            return innerDictionary.Count;
        }
    }

    public bool IsReadOnly
    {
        get
        {
            return innerDictionary.IsReadOnly;
        }
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return innerDictionary.Remove(item);
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return innerDictionary.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return innerDictionary.GetEnumerator();
    }
}

Frankly I don't understand the point of the contract. The contract is

 Contract.Ensures(!Contract.Result<bool>() || Count > 0);

What are you trying to say? You can neither guarantee that the dictionary contains the key, nor that the dictionary contains any values at all. So this contract can't always be met. That's what the verifier is telling you: it can't prove that this statement you are promising to be true is true.

The best you can ensure that the return value is true or the return value is false and that Count is greater than zero or equal to zero But what's the point of such a contract? The caller already knows this.

Given that, I wouldn't bother with a contract here at all.

链接地址: http://www.djcxy.com/p/74410.html

上一篇: 在JDBC中检查请求是否正确执行

下一篇: 代码合同:确保未经证实和需要未经证实