Code Contracts: provides unproven and requires unproven

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

I have a custom dictionary wrapper class, and here is the code snippet that is needed.

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 a line for ContainsKey is because I got the following warning message (and so far): Codecontracts: ensures unproven: !Contract.Result<bool>() || @this.Count > 0 Codecontracts: ensures unproven: !Contract.Result<bool>() || @this.Count > 0 . I can delete this line and get the SECRET CHOICE !

What should I do to get rid of these problems?


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)', so you cannot add Required.

+6
source share
2 answers

"I have a custom class wrapper class" that implements IDictionary<TKey, TValue> . Interface methods can specify contracts, and class methods that implement them must correspond to contracts. In this case, IDictionary<TKey, TValue>.ContainsKey(TKey) has the contract you are 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 this, we can translate this into English:

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

This is a perfectly reasonable requirement. An empty dictionary should not require 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 is innerDictionary.Count is a solid guarantee that other methods can rely on. It adds a similar Contract.Ensures to ContainsKey , so the IDictionary<TKey, TValue>.TryGetValue 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(); } } 
+5
source

Honestly, I do not understand the meaning of the contract. the contract

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

What are you trying to say? You cannot guarantee that the dictionary contains a key, or that the dictionary contains any meanings at all. Therefore, this contract cannot always be satisfied. This is what the verifier tells you: it cannot prove that this statement that you promise to be true is true.

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

Given this, I would not discuss the contract at all.

+1
source

Source: https://habr.com/ru/post/897327/


All Articles