正确使用CodeContract需要

时间:2013-03-15 21:10:17

标签: .net c#-4.0 code-contracts

基本上我想知道是否使用代码契约来确定ConcurrentDictionary中是否存在密钥是代码契约的可接受使用。它对我来说不合适,因为它不仅仅是参数检查,因为它取决于运行时字典的状态。

public class MyClass
{
    private ConcurrentDictionary<string, object> someItems = 
        new ConcurrentDictionary<string, object>();

    public object GetItem(string itemName)
    {
        Contract.Requires<ArgumentNullException>(!String.IsNullOrWhiteSpace(itemName));

        // ?? Is this a correct alternative to checking for null???
        Contract.Requires<KeyNotFoundException>(someItems.ContainsKey(itemName));

        return someItems[itemName];
    }
}

但是如果没问题的话,这是一个更简洁的方法,它有2个Contract.Requires和一个返回,通过下面的传统方式。

public class MyClass
{
    private ConcurrentDictionary<string, object> someItems = 
        new ConcurrentDictionary<string, object>();

    public object GetItem(string itemName)
    {
        Contract.Requires<ArgumentNullException>(!String.IsNullOrWhiteSpace(itemName));

        // Traditional null check
        var item = someItems[itemName];

        if (item == null)
        {
            throw new KeyNotFoundException("Item " + itemName + " not found.");
        }

        return item;            
    }
}

1 个答案:

答案 0 :(得分:0)

对我来说有点奇怪:类的内部状态(即someItems字典的内容)绝对是合同的一部分。你可以以这种方式使用它,但是合同检查应该让调用者知道到底出了什么问题。在这种情况下,调用者永远不会猜出哪些参数是允许的,哪些不是 - 即使在获得KeyNotFoundException之后。

此外,在这种特殊情况下,如果在字典中找不到对象则抛出异常看起来不一致,在我看来返回null会更有意义。

顺便说一句,在你的第一个例子中,itemName在字典中被搜索了两次。