如何使用委托和/或事件推迟集合中每个项目上事件的执行,直到集合迭代完成?

发布于 2024-08-28 15:45:36 字数 1209 浏览 8 评论 0原文

值得注意:这更像是一个好奇问题。

给定一个 List,其中每个窗口都有一个附加到 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() 方法中,如何迭代集合以调用关闭事件,但将引发事件推迟到集合完全迭代之后?

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 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

国产ˉ祖宗 2024-09-04 15:45:36

想必您正在尝试避免第一种情况下的“集合已修改”异常。

实际上,“推迟”此操作的唯一方法是制作集合的副本,这涉及完全迭代原始集合并将项目添加到新集合中:

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

此外,第二种方法是有效的,尽管通常在需要清理时索引集合(例如 List)中的实例,您只需通过倒计时即可完成:

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

就我个人而言,我认为没有理由通过更多委托使问题复杂化。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文