“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
,如果搜索没有返回任何结果,我将返回一个默认值数组。使用者应该只收到一个可以枚举的列表,而不是修改的列表。
这里的"多重枚举"在哪里?如果确实有一个,这不是在这种情况下使用的最佳类型吗?
多重枚举潜力是你调用Any
,这将导致第一个枚举,然后由该方法的调用者进行潜在的第二次枚举。
在这种情况下,我猜它基本上可以保证至少会发生两个枚举。
存在警告是因为IEnumerable
可以伪装一些昂贵的东西,例如数据库调用(很可能是IQueryable
(,并且由于IEnumerable
没有缓存作为其协定的一部分,它将重新枚举源新鲜。这可能会导致以后的性能问题(我们被这个惊人的数量刺痛了,我们甚至不使用IQueryable
,我们的是在域模型遍历(。
仍然只是一个警告,如果您意识到多次调用通过潜在慢速源调用可枚举的潜在费用,则可以禁止它。
缓存结果的标准答案是 ToList
或 ToArray
.
尽管我确实记得曾经制作过IEnumerable
的IRepeatable
版本,并在进行过程中进行内部缓存。这在我的免费代码库的深处丢失了:-(
>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 不支持此重载。