我有这段代码:
return children.SelectMany(c => GetChildControls<TControl>(c)).Concat(children);
......并且Resharper建议我将其更改为:
return children.SelectMany(GetChildControls<TControl>).Concat(children);
在上下文中:
internal static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
{
var children = control.Controls != null ? control.Controls.OfType<TControl>() : Enumerable.Empty<TControl>();
return children.SelectMany(GetChildControls<TControl>).Concat(children);
}
正如您所看到的那样,差异在于该行的“改进”版本已经省略了插入的“(c)”
但现在它标志着可疑,说,“可能多次枚举IEnumerable”
是的,那是对的,可能/应该有多个,但为什么会这样做呢?我应该将它恢复到以前的状态吗?
答案 0 :(得分:2)
ReSharper为您提供的问题是,您要两次枚举children
。具体来说,您第一次在children
拨打电话时枚举children.SelectMany(GetChildControls<TControl>)
,而在您拨打.Concat(children)
时再次点名internal static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
{
var children = control.Controls.OfType<TControl>().ToList();
return children.SelectMany(GetChildControls<TControl>).Concat(children);
}
。 ReSharper会对此发出警告,因为每次枚举都可能导致不同的结果,或者每次枚举都可能代价高昂。有关详细信息,请参阅this question。
一种解决方案是
children
确保Collection.find()
在你创建它之后不会在你的方法中发生变化(当然,除非你自己改变它),并且它只会被枚举一次。