开发者

How to defer execution of an Event on each item in a collection until iteration of collection is complete using delegates and/or events?

开发者 https://www.devze.com 2022-12-26 05:07 出处:网络
Of Note: This is more of a curiosity question than anything else. Given a List<Window> where each window has an event attached to the Close Event which removes the window from the collection, h

Of Note: This is more of a curiosity question than anything else.

Given a List<Window> where each window has an event attached to the Close Event which removes the window from the collection, how could you use delegates / events to defer the execution of the Close Event until the collection has been iterated?

For example:

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 开发者_Go百科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();
        } 
    }

}

Specifically, within the CloseAllWindows() method, how could you iterate the collection to call the close event, but defer the event being raised until the collection has been completely iterated?


Presumably you're trying to avoid the "Collection was modified" exception in the first case.

Really the only way to "defer" this is to make a copy of the collection, which involves iterating the original collection fully and adding the items to a new collection:

var openedWindowsCopy = new List<Window>(OpenedWindows);
foreach (var window in openedWindowsCopy)
    window.Close();

Also, your second method is valid, although typically when you need to clean up instances in an indexed collection such as a List<T>, you do it simply by counting down:

for (int i = OpenedWindows.Count - 1; i >= 0; i--)
    OpenedWindows[i].Close();

Personally, I see no reason to complicate the issue with more delegates.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号