C#中优雅地处理集合中未找到项的方法

12

我有以下情况:

  1. 我有一个foreach循环,它遍历一个集合,如果找到符合条件的项目(如下例所示),则返回该项目。

如果没有找到,最优雅的处理方法是什么?我使用了throw new notimplementedexception,但我认为还有更优雅的方式。

代码如下:

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

 throw new NotImplementedException(); 

正如您所看到的,这不是我所称之为易读的代码。我应该如何使其更容易维护?附带说一句,从技术角度来看,它确实完成了应有的功能。

5个回答

12
“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);

我猜,我没有正确地提问。让我担心的是在“工作完成”部分后面直接跟着一个“挂起”的抛出。无论异常类型如何,这几乎感觉是错误的。如果代码到达这一点……肯定有问题。这是可以接受的,还是会造成不良影响? - JL.
@JL:在我看来,这是完全可以接受的。当然,如果可能的话,最好一开始就使用LINQ。如果你觉得不明显为什么要这样做,你总可以使用注释——但我希望方法本身的文档能更清晰地解释它。 - Jon Skeet
我喜欢让调用者决定结果的真正含义。如果这是一件非常糟糕的事情,那么就抛出异常。否则,让调用者决定空结果是否值得抛出。如果找不到您的类型,有多致命?如果选择try..catch或null处理之间,我会选择null处理。但是,如果需要将异常上升到外部处理,则手头就束缚了... - Pete M
你不能直接使用 Linq 与 SPContentTypeCollection。你需要先使用 .Cast<SPContentType>()。 - John Fouhy
@JohnFouhy:已添加,谢谢。我很惊讶原帖作者当时没有提到它。 - Jon Skeet

4

这取决于是一个预期的情况还是一个异常情况。

如果您要比较的项目传递给了一个方法,并且集合中确实应该 总是 有匹配的项目,那么我会抛出一个 ArgumentOutOfRangeException 异常。

如果预计有时找不到匹配的项目,则只需返回 null 来表示未找到请求的项目。


3

NotImplementedException明显不是正确的异常。我更倾向于抛出一个自定义异常,例如ElementNotFoundInCollection。

另一种方法是返回null。然后你需要在调用端检查返回的对象是否为null。


2

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

  1. myDic[key]

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

    • 优点:如果未找到键,则不会抛出异常(但返回false
    • 缺点:只能获取值,不能设置

因此,如果您只需要获取一个值,并且不想抛出异常,则第二种方法显然更可取。

因此,在您的情况下,编写函数类似于:

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

2

我同意Rofl的看法,NotImplemented是错误的。如果你不想定义自己的异常类,KeyNotFoundException是相当接近的。

返回null也是一种选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接