C# ToolStripItemCollection.AddRange方法中存在缺陷?

C# ToolStripItemCollection.AddRange方法中存在缺陷?,c#,.net,winforms,C#,.net,Winforms,我坚信在ToolStripItemCollection.AddRange的实现中是一个错误: 我用两个菜单制作了Windows窗体应用程序,每个菜单包含两个项目 (对不起,我没有足够的声誉来发布图片) 接下来,我将实现按钮单击处理程序: private void button1_Click(object sender, EventArgs e) { menu1.DropDownItems.AddRange(menu2.DropDownItems); } 并引发System.Argu

我坚信在ToolStripItemCollection.AddRange的实现中是一个错误:

我用两个菜单制作了Windows窗体应用程序,每个菜单包含两个项目

(对不起,我没有足够的声誉来发布图片)

接下来,我将实现按钮单击处理程序:

private void button1_Click(object sender, EventArgs e)
{
    menu1.DropDownItems.AddRange(menu2.DropDownItems);
}
并引发System.ArgumentOutOfRangeException

我非常好奇为什么会发生这种情况,我用ILSpy反编译了ToolStripItemCollection程序集。这就是我看到的:

public void AddRange(ToolStripItemCollection toolStripItems)
{
    if (toolStripItems == null)
    {
        throw new ArgumentNullException("toolStripItems");
    }
    if (this.IsReadOnly)
    {
        throw new NotSupportedException(SR.GetString("ToolStripItemCollectionIsReadOnly"));
    }
    using (new LayoutTransaction(this.owner, this.owner, PropertyNames.Items))
    {
        int count = toolStripItems.Count;
        for (int i = 0; i < count; i++)
        {
            this.Add(toolStripItems[i]);
        }
    }
}
并最终进入ToolStripItemCollection.SetOwner:

private void SetOwner(ToolStripItem item)
{
    if (this.itemsCollection && item != null)
    {
        if (item.Owner != null)
        {
            item.Owner.Items.Remove(item);
        }
        item.SetOwner(this.owner);
        if (item.Renderer != null)
        {
            item.Renderer.InitializeItem(item);
        }
    }
}
我们可以清楚地看到,对于循环,在每个步骤中都从toolStripItems中删除item。MSDN对ToolStripItemCollection实现的IList接口发表了评论: 在连续元素的集合(如列表)中,删除元素之后的元素向上移动以占据空出的位置。如果集合已编制索引,则移动的元素的索引也会更新。
结果,我们最终在错误索引上访问toolStripItems中的项(第二个项移动到位置0)。我说的对吗?

不是100%确定问题是什么,但您可以通过将集合转换为数组(需要强制转换)来解决这个问题:

menu1.DropDownItems.AddRange(menu2.DropDownItems.Cast().ToArray());

您的版本引发错误的原因是,当第一个菜单添加到下拉集合时,它将从其迭代的集合中删除,因此出现OutOfRange异常。

当然,它不是为了处理您的场景而编写的。这些项目已拥有所有者是故障模式。您必须复制集合,以便在对其进行迭代时不能对其进行修改。顺便说一句,这是一个很常见的问题。问题是:这个方法有缺陷还是我遗漏了什么。当我有机会使用适当的方法时,我不想做出难看的造型。
private void SetOwner(ToolStripItem item)
{
    if (this.itemsCollection && item != null)
    {
        if (item.Owner != null)
        {
            item.Owner.Items.Remove(item);
        }
        item.SetOwner(this.owner);
        if (item.Renderer != null)
        {
            item.Renderer.InitializeItem(item);
        }
    }
}
menu1.DropDownItems.AddRange(menu2.DropDownItems.Cast<ToolStripItem>().ToArray());