Как отложить выполнение события для каждого элемента в коллекции до завершения итерации коллекции с использованием делегатов и / или событий? - PullRequest
0 голосов
/ 12 апреля 2010

Примечание : Это скорее вопрос любопытства, чем что-либо еще.

Учитывая List<Window>, где каждое окно имеет событие, прикрепленное к событию Close, которое удаляет окно из коллекции, как вы могли бы использовать делегаты / события, чтобы отложить выполнение события Close до тех пор, пока коллекция не будет повторена?

Например:

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, но отложить возникновение события до полной итерации коллекции?

1 Ответ

0 голосов
/ 12 апреля 2010

Предположительно, вы пытаетесь избежать исключения "Коллекция была изменена" в первом случае.

Действительно, единственный способ «отложить» это сделать копию коллекции, которая включает в себя полную итерацию исходной коллекции и добавление элементов в новую коллекцию:

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

Кроме того, ваш второй метод действителен, хотя обычно, когда вам нужно очистить экземпляры в индексированной коллекции, такой как List<T>, вы делаете это просто путем отсчета:

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

Лично я не вижу причин усложнять проблему с большим количеством делегатов.

...