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

Use*_*ser 20 c# resharper ienumerable

关于"可能存在多个枚举"的SO有一个问题,但这个问题更具体.

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

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

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

return (!ReferenceEquals(enumerable, null) || enumerable.Any());
Run Code Online (Sandbox Code Playgroud)

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

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

tda*_*ers 30

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

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

  • 例如,您的枚举可以从网络流中读取字节(这将构成副作用).如果你枚举一次,一切都很好,并且一次性开始读取流.但是,如果您中止第一次迭代然后再次迭代,即使底层网络流无法向后搜索,您很可能会遇到不希望的行为. (12认同)

Aak*_*shM 8

正如@tdammers所指出的那样,所提到的"多个枚举"是Any和所需的两个枚举All.由于你想要拒绝一个空序列,我能想到的最好的是:

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;
}
Run Code Online (Sandbox Code Playgroud)