0

注意:これは何よりも好奇心の質問です。

各ウィンドウ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イベントを呼び出すことができますが、コレクションが完全に反復されるまで、発生するイベントを延期できますか?

4

1 に答える 1

0

おそらく、最初のケースで「コレクションが変更されました」という例外を回避しようとしています。

これを「延期」する唯一の方法は、コレクションのコピーを作成することです。これには、元のコレクションを完全に反復し、アイテムを新しいコレクションに追加することが含まれます。

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

また、2番目の方法は有効ですが、通常、などのインデックス付きコレクション内のインスタンスをクリーンアップする必要がある場合は、List<T>カウントダウンするだけでクリーンアップできます。

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

個人的には、より多くの代表者が問題を複雑にする理由はないと思います。

于 2010-04-11T22:59:26.060 に答える