首页 文章

“可能多次枚举IEnumerable”问题?

提问于
浏览
1

我正在使用Resharper得到一个可能的多个IEnumerable枚举,而我真的是一个问题 . 这是我的方法:

public IEnumerable<Contact> GetContacts(IContactManager contactManager, string query)
{
    IEnumerable<Contact> contacts = contactManager.GetContacts(query);
    if (contacts.Any()) return contacts; // Get the warning on this line
    // Do some other stuff
    return new[] {
        new Contact { Name = "Example" }
    }
}

应该是显而易见的,但我正在搜索 Contact ,如果搜索没有返回结果,我将返回一个默认值数组 . 消费者应该只收到一个可以枚举但不能修改的列表 .

这里的“多重枚举”在哪里?如果确实有一个,这不是在这种情况下使用的最佳类型吗?

2 回答

  • 3

    多重枚举的可能性是您调用 Any ,这将导致第一次枚举,然后由该方法的调用者进行潜在的第二次枚举 .

    在这种情况下,我猜大多数保证两个枚举至少会发生 .

    警告的存在是因为 IEnumerable 可以伪装一些昂贵的东西,例如数据库调用(很可能是 IQueryable ),并且作为 IEnumerable 不 Contract ,它将重新枚举源新鲜 . 这可能会导致以后的性能问题(我们已经被这种惊人的数量所刺激,我们甚至不使用 IQueryable ,我们的是域模型遍历) .

    也就是说,它仍然只是一个警告,如果你知道多次调用可枚举的潜在慢源的潜在费用,那么你可以抑制它 .

    缓存结果的标准答案是 ToListToArray .

    虽然我确实记得在内部缓存过程中制作一个IEnumerable的IRepeatable版本 . 这在我的免费代码库的深处丢失了:-)

  • 5

    Enumerable.Any 执行查询以检查sequnce是否包含元素 . 如果没有元素,您可以使用DefaultIfEmpty提供不同的默认值:

    public IEnumerable<Contact> GetContacts(IContactManager contactManager, string query)
    {
        IEnumerable<Contact> contacts = contactManager.GetContacts(query)
            .DefaultIfEmpty(new Contact { Name = "Example" });
        return contacts;
    }
    

    请注意,LINQ-To-SQL不支持此重载 .

相关问题