2011-09-14 30 views
6

Tôi không chắc mình có đang làm gì sai ở đây hay không ...Hợp đồng mã: Đảm bảo Unproven & Yêu cầu Unproven

Tôi có lớp trình bao bọc từ điển tùy chỉnh và đây là đoạn trích của mã cần thiết.

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); 
} 

Lý do duy nhất tôi thêm dòng cho ContainsKey là vì tôi nhận được thông báo cảnh báo sau (và vẫn làm): Codecontracts: ensures unproven: !Contract.Result<bool>() || @this.Count > 0. Tôi có thể xóa dòng này và vẫn nhận được CÂU CHUYỆN CÙNG!

Tôi phải làm gì ở đây để loại bỏ những vấn đề này?


Cập nhật:

Tôi cũng đã cố gắng (như đề xuất) ...

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

    return InternalDictionary.ContainsKey(key); 
} 

Cảnh báo 5 Phương pháp 'My.Collections.Generic.ReadOnlyDictionary 2.ContainsKey(type parameter.TKey)' implements interface method 'System.Collections.Generic.IDictionary 2.ContainsKey (loại parameter.TKey) ', do đó không thể thêm Yêu cầu.

+0

Lưu ý rằng gốc của vấn đề của bạn là phương pháp này hứa hẹn rằng mọi khóa sẽ được tìm thấy và nó thực sự không kiểm soát được điều đó. –

Trả lời

1

Thành thật mà nói, tôi không hiểu điểm của hợp đồng. Hợp đồng là

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

Bạn đang cố gắng nói gì? Bạn không thể đảm bảo rằng từ điển chứa khóa, cũng không phải từ điển chứa bất kỳ giá trị nào. Vì vậy, hợp đồng này không phải lúc nào cũng được đáp ứng. Đó là những gì người xác minh đang nói với bạn: nó không thể chứng minh rằng tuyên bố này bạn hứa hẹn là đúng.

Điều tốt nhất bạn có thể đảm bảo rằng giá trị trả về là true hoặc giá trị trả về là falseCount là lớn hơn không hoặc bằng số không Nhưng điểm của một hợp đồng như vậy là gì? Người gọi đã biết điều này.

Cho rằng, tôi sẽ không bận tâm với hợp đồng ở đây chút nào.

+0

Trong câu hỏi của tôi, tôi đã nói rằng lý do duy nhất tôi thêm vào hợp đồng đó là vì thông điệp cảnh báo đã nói với tôi. Tôi nhận được cảnh báo tương tự có hoặc không có nó, và thẳng thắn tôi thậm chí không hiểu những gì nó đang cố gắng để nói. – michael

+0

@michael: bắt đầu lại. Đây không phải là hợp đồng đầu tiên phải không? –

+0

Ban đầu, tôi không có hợp đồng trong mã. CodeContracts phàn nàn và tôi đã đặt hợp đồng vào đó vì những gì nó đã nêu. Sau đó, tôi nhận được thông báo cảnh báo tương tự. Về cơ bản, ngay cả khi phương thức không có ** BẤT K ** ** mã hợp đồng, nó vẫn đưa ra cảnh báo tương tự. – michael

5

"Tôi có lớp trình bao bọc từ điển tùy chỉnh" - thực hiện IDictionary<TKey, TValue>. Các phương thức giao diện có thể chỉ định các hợp đồng và các phương thức lớp thực hiện chúng phải đáp ứng các hợp đồng. Trong trường hợp này, IDictionary<TKey, TValue>.ContainsKey(TKey) có hợp đồng bạn đang hỏi về:

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

Một cách logic, !a || b thể được đọc như a ===> b (a ngụ ý b), và sử dụng đó, chúng ta có thể dịch này để tiếng Anh:

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

Đây là một yêu cầu hoàn toàn hợp lý. Từ điển trống không được yêu cầu chứa khóa. là những gì bạn cần chứng minh.

Đây là mẫu DictionaryWrapper lớp bổ sung Contract.Ensures để hứa rằng chi tiết triển khai Count bằng innerDictionary.Count là một đảm bảo khó khăn mà các phương pháp khác có thể dựa vào.Nó thêm một số Contract.Ensures tương tự vào ContainsKey để hợp đồng IDictionary<TKey, TValue>.TryGetValue cũng có thể xác minh được.

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(); 
    } 
} 
+0

+1 cho lớp logic tuyệt vời. Tôi đã vấp phải những hợp đồng có điều kiện trước đây và quên đi bản sắc đó về hàm ý từ các lớp toán rời rạc của tôi xD. – julealgon

Các vấn đề liên quan