在C#中处理集合中找不到的项目的优雅方式

时间:2011-04-04 16:11:31

标签: c#

我有以下情况:

  1. 我有一个循环遍历集合的foreach循环,如果找到了一个项目(基于下面示例中的条件),它将返回该项目。
  2. 如果不是,处理此异常的最优雅方式是什么。我有一个新的notimplementedexception,但我认为有一个更优雅的方式。

    代码是:

     foreach (SPContentType type in sPContentTypeCollection)
                {
                    if (type.Name == contentTypeName)
                    {
                        return type; 
                    }
                }
    
     throw new NotImplementedException(); 
    

    正如您所看到的,这不是我所谓的可读代码。如何让下一个人更容易维护。从侧面说明,它从技术角度出发应该做的事情。

5 个答案:

答案 0 :(得分:10)

NotImplementedException肯定是不合适的,因为你已经实现了这个方法......但是应该你应该抛出什么样的异常?说实话,这取决于具体情况。

有时返回null表示缺少值是合适的。其他时候,抛出异常很好 - 例如可能是InvalidOperationException。如果这种情况表示某些描述的错误,而不是调用者应该发生的完全合理的情况,则应抛出异常。

至于其余的代码......如果你使用的是.NET 3.5,你可以使用LINQ:

return sPContentTypeCollection.Cast<SPContentType>()
                              .First(type => type.Name == contentTypeName);

如果找不到名字,那将自动为您抛出InvalidOperationException。或者,如果要返回null:

// type shortened to t to avoid scrollbars...
return sPContentTypeCollection.Cast<SPContentType>()
                              .FirstOrDefault(t => t.Name == contentTypeName);

答案 1 :(得分:3)

NotImplementedException绝对是错误的异常。我宁愿抛出一个自定义异常,例如ElementNotFoundInCollection。

另一种方法是返回null。然后,如果返回的对象不为空,则必须检查调用端。

答案 2 :(得分:3)

这实际上取决于这是预期还是例外情况。

如果你比较的项目被传递给一个方法,那么总是应该是集合中的匹配项目,我会抛出ArgumentOutOfRangeException例外。

如果预计有时没有找到匹配的项目,我只会返回null以表示找不到所请求的项目。

答案 3 :(得分:2)

我同意Rofl的说法NotImplemented是错误的。如果您不想定义自己的异常类,KeyNotFoundException非常接近。

返回null也是一种选择。

答案 4 :(得分:2)

嗯,看看.NET框架本身如何在自己的类中处理这种情况可能是值得的。例如,取Dictionary<TKey, TValue>。有两种方法可以从字典中获取值:

  1. myDic[key]

    • 优势:短;可以分配给(因此可以使用++和类似的运算符)
    • 缺点:如果密钥不存在,则抛出KeyNotFoundException
  2. myDic.TryGetValue(key, out value)

    • 优势:如果未找到密钥,则不会抛出(但会返回false
    • 缺点:只能获得价值,而不能设置
  3. 因此,如果您只需获取一个值,并且您不想抛出异常,那么第二个显然更可取。

    因此,在您的情况下,请以类似方式编写函数:

    public bool TryGetType(string contentTypeName, out SPContentType result)
    {
        foreach (SPContentType type in sPContentTypeCollection)
        {
            if (type.Name == contentTypeName)
            {
                result = type;
                return true;
            }
        }
        result = default(SPContentType);
        return false;
    }