C# 如何使用委托和/或事件延迟集合中每个项上事件的执行,直到集合的迭代完成为止?
值得注意的是:这更像是一个好奇的问题 给定一个列表,其中每个窗口都有一个附加到关闭事件的事件,该事件将窗口从集合中删除,您如何使用委托/事件延迟关闭事件的执行,直到集合被迭代 例如:C# 如何使用委托和/或事件延迟集合中每个项上事件的执行,直到集合的迭代完成为止?,c#,events,delegates,deferred-execution,C#,Events,Delegates,Deferred Execution,值得注意的是:这更像是一个好奇的问题 给定一个列表,其中每个窗口都有一个附加到关闭事件的事件,该事件将窗口从集合中删除,您如何使用委托/事件延迟关闭事件的执行,直到集合被迭代 例如: public class Foo { private List<Window> OpenedWindows { get; set; } public Foo() { OpenedWindows = new List<Window>(); }
public class Foo
{
private List<Window> OpenedWindows { get; set; }
public Foo()
{
OpenedWindows = new List<Window>();
}
public void AddWindow( Window win )
{
win.Closed += OnWindowClosed;
OpenedWindows.Add( win );
}
void OnWindowClosed( object sender, EventArgs e )
{
var win = sender as Window;
if( win != null )
{
OpenedWindows.Remove( win );
}
}
void CloseAllWindows()
{
// obviously will not work because we can't
// remove items as we iterate the collection
// (the close event removes the window from the collection)
OpenedWindows.ForEach( x => x.Close() );
// works fine, but would like to know how to do
// this with delegates / events.
while( OpenedWindows.Any() )
{
OpenedWindows[0].Close();
}
}
}
具体地说,在CloseAllWindows方法中,您如何迭代集合以调用close事件,但将引发的事件推迟到集合完全迭代之后?在第一种情况下,您可能试图避免集合被修改异常 实际上,推迟此操作的唯一方法是制作集合的副本,这包括完全迭代原始集合并将项目添加到新集合:
var openedWindowsCopy = new List<Window>(OpenedWindows);
foreach (var window in openedWindowsCopy)
window.Close();
就我个人而言,我认为没有理由让更多的代表将问题复杂化。谢谢你的回答。我意识到我把问题复杂化了,但我想看看是否还有其他办法。我想我应该使用/添加将列表复制到新列表的示例,但我认为问题很清楚,我正在寻找复杂的版本@Metro:此复制版本完全符合您的规范。它迭代整个集合,但在迭代整个集合之前不会关闭任何窗口。任何试图延迟Close方法执行的实现都必须保存所有迭代的元素,以便稍后执行它们;这与复制完全相同。您可以编写一个扩展方法来封装复制和运行语义,但它的效率将低于此答案中的第二个索引版本;就像我说的,这是出于好奇。换句话说,不管最佳实践如何,您将如何以复杂的方式进行?谢谢你的回答,我理解你的意思。现在,准备好和我一起下兔子洞了吗?@Metro:我真的不明白你的意思。编写一个扩展方法,该方法接受一个操作,遍历序列,将每个元素保存在列表或堆栈中,然后对保存的元素执行该操作。基本上与顶部的代码相同,只是在方法内部。也许如果你能解释一下你认为应该发生什么/应该发生什么不同,我可以说得更详细。@Aaaron-对延迟的回复表示歉意。不管它有多么空洞,是否有一种方法可以在ForEach循环内部将close操作推入委托,但在循环完成之前不调用委托?
for (int i = OpenedWindows.Count - 1; i >= 0; i--)
OpenedWindows[i].Close();