“IEnumerable 的可能多重枚举”问题

本文关键字:枚举 问题 IEnumerable | 更新日期: 2023-09-27 18:00:32

我正在使用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,如果搜索没有返回任何结果,我将返回一个默认值数组。使用者应该只收到一个可以枚举的列表,而不是修改的列表。

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

“IEnumerable 的可能多重枚举”问题

多重枚举潜力是你调用Any,这将导致第一个枚举,然后由该方法的调用者进行潜在的第二次枚举。

在这种情况下,我猜它基本上可以保证至少会发生两个枚举。

存在警告是因为IEnumerable可以伪装一些昂贵的东西,例如数据库调用(很可能是IQueryable(,并且由于IEnumerable没有缓存作为其协定的一部分,它将重新枚举源新鲜。这可能会导致以后的性能问题(我们被这个惊人的数量刺痛了,我们甚至不使用IQueryable,我们的是在域模型遍历(。

也就是说,它

仍然只是一个警告,如果您意识到多次调用通过潜在慢速源调用可枚举的潜在费用,则可以禁止它。

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

尽管我确实记得曾经制作过IEnumerableIRepeatable版本,并在进行过程中进行内部缓存。这在我的免费代码库的深处丢失了:-(

>Enumerable.Any执行查询以检查后续是否包含元素。如果没有元素,您可以使用 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 不支持此重载。