首页 文章

甚至“IsNullOrEmpty”检查也会给出“可能多次枚举IEnumerable”的警告

提问于
浏览
20

已经有question on SO about "possible multiple enumerations",但这个问题更具体 .

请考虑以下方法,该方法将 IEnumerable<string> 作为输入并对其每个元素执行给定方法:

public static bool SomeMethod(IEnumerable<string> enumerable)
{
    if (enumerable.IsNullOrEmpty())
    {
        // throw exception.
    }
    else
    {
        return (enumerable.All(SomeBooleanMethod));
    }
}

在上面的代码中, IsNullOrEmpty 只是一个运行的扩展方法

return (!ReferenceEquals(enumerable, null) || enumerable.Any());

问题是ReSharper警告我“IEnumerable的可能的多个枚举”,我真的不知道这是否真的是一个问题 .

我理解警告的含义,但是如果你真的需要在无效或空洞的情况下检查并抛出异常,你在这种情况下真的可以做些什么?

2 回答

  • 30

    这意味着你(部分地)在IEnumerable上多次迭代:首先调用 Any() (它需要至少初始化迭代以查看枚举是否返回任何元素),以及第二次在 All 中(迭代)从最开始) .

    ReSharper对此提出警告的原因是枚举可枚举可能会导致副作用,无意中迭代两次可能会触发副作用两次,这可能是也可能不是 .

  • 8

    正如@tdammers所标识的那样,"multiple enumerations"引用的是 AnyAll 所需的两个枚举 . 由于你想要拒绝一个空序列,我能想到的最好的是:

    public static bool SomeMethod(IEnumerable<string> enumerable)
    {
        if (enumerable == null)
            throw new ArgumentNullException();
    
        // Manually perform an All, keeping track of if there are any elements
        bool anyElements = false;
    
        bool result = true;
    
        foreach (string item in enumerable)
        {
            anyElements = true;
            result = result && SomeBooleanMethod(item);
    
            // Can short-circuit here
            if (!result)
                break;
        }
    
        if (!anyElements)
            throw new ArgumentException();    // Empty sequence is invalid argument
    
        return result;
    }
    

相关问题