Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用委托和/或事件延迟集合中每个项上事件的执行,直到集合的迭代完成为止?_C#_Events_Delegates_Deferred Execution - Fatal编程技术网

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();