msa*_*het 4 .net c# enumeration
这是我正在探索的东西,看看我是否可以采取的是什么
List<MdiChild> openMdiChildren = new List<MdiChild>();
foreach(child in MdiManager.Pages)
{
openMdiChildren.Add(child);
}
foreach(child in openMdiChild)
{
child.Close();
}
Run Code Online (Sandbox Code Playgroud)
并缩短它不需要2个foreach循环.
注意我已经更改了调用对象的内容以简化此示例(这些来自第三方控件).但是对于信息和理解
MdiManager.Pages继承形式CollectionBase,而形式又继承IEnumerable
并MdiChild.Close()从MdiManager.PagesCollection中删除open子,从而改变集合并导致枚举在枚举期间修改集合时抛出异常,例如.
foreach(child in MdiManage.Pages)
{
child.Close();
}
Run Code Online (Sandbox Code Playgroud)
我能工作的双foreach至
((IEnumerable) MdiManager.Pages).Cast<MdiChild>.ToList()
.ForEach(new Action<MdiChild>(c => c.Close());
Run Code Online (Sandbox Code Playgroud)
为什么在枚举期间没有相同的问题来处理修改集合?我最好的猜测是,当对ToList调用创建的List进行枚举时,它实际上是对MdiManager.Pages集合中的匹配项而不是生成的List 执行操作.
编辑
我想说清楚我的问题是如何简化这个问题,我只是想了解为什么在我执行它时修改集合没有问题,因为我现在已经编写了它.
您的致电ToList()是为您节省的,因为它基本上复制了您在上面所做的事情.ToList()实际创建一个List<T>(List<MdiChild>在这种情况下为a)包含所有元素MdiManager.Pages,然后你的后续调用ForEach操作该列表,而不是MdiManager.Pages.
最后,这是一个风格偏好的问题.我个人并不ForEach喜欢这个功能(我更喜欢查询组合功能Where,ToList()因为它们的简单性以及它们的设计不会对原始源产生副作用,而事实ForEach并非如此).
你也可以这样做:
foreach(child in MdiManager.Pages.Cast<MdiChild>().ToList())
{
child.Close();
}
Run Code Online (Sandbox Code Playgroud)
从根本上说,这三种方法完全相同(它们将内容缓存MdiManager.Pages到a中List<MdiChild>,然后迭代缓存列表并调用Close()每个元素.