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

本文关键字:方式 找不到 处理 集合 | 更新日期: 2023-09-27 17:48:59

我有以下场景:

  1. 我有一个foreach循环,循环通过一个集合,如果找到一个项目(基于标准,如下面的例子),它将返回该项目。

如果不是,处理这个异常的最优雅的方法是什么?我有一个抛出新的notimented异常,但我认为有一个更优雅的方式。

代码是:

 foreach (SPContentType type in sPContentTypeCollection)
            {
                if (type.Name == contentTypeName)
                {
                    return type; 
                }
            }
 throw new NotImplementedException(); 
如你所见,这不是我所说的可读代码。我怎样才能让下一个人更容易维护。另一方面,从技术角度来看,它做了它应该做的事情。

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

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

这实际上取决于这是预期情况还是异常情况。

如果你比较的项目被传递给一个方法,真的有总是应该是一个匹配的项目在集合中,我会抛出一个ArgumentOutOfRangeException异常。

如果预期有时没有找到匹配的项目,我只返回null来指示未找到所请求的项目。

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

另一种方法是直接返回null。然后,您必须在调用端检查返回的对象是否为null。

我同意Rofl认为notimented是错误的。如果你不想定义自己的异常类,KeyNotFoundException非常接近。

返回null也是一个选项

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

  1. myDic[key]

    • 优势:短;可以赋值给(因此可以使用++和类似的操作符)
    • 缺点:如果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;
}