首页 > 解决方案 > 修改源项目会更改列表项目?

问题描述

我正在为使用 C# 中的 Windows 窗体的软件编写一个小插件。我需要解析一个 XML 文件来检索一些对象并将它们添加到ListBox. 问题是在我的程序结束时,所有对象都与最后添加的对象相同。我有点想通为什么,但我仍在寻找如何解决它。这是一个用 aString[]而不是我的对象的小例子:

static void Main(string[] args)
{
    ListBox listbox = new ListBox();
    String[] s = new string[] { "5", "2", "3" };
    listbox.Items.Add(s);
    s[2] = "0";
    listbox.Items.Add(s);

    Console.WriteLine(((String[])listbox.Items[0])[2]); // result => 0
    Console.WriteLine(((String[])listbox.Items[1])[2]); // result => 0
    Console.ReadLine();
}

标签: c#winformslistbox

解决方案


listbox.Items.Add(s);您只添加一项是数组本身。AddRange改为使用添加数组的元素。

listbox.Items.AddRange(s);

使其工作的另一种方法是设置DataSource

listbox.DataSource = s;

让我们详细看看您的代码中发生了什么(带有行号)

1    String[] s = new string[] { "5", "2", "3" };
2    listbox.Items.Add(s);
3    s[2] = "0";
4    listbox.Items.Add(s);
  1. 创建并初始化一个数组。
  2. 该数组作为一个项目添加到 ListBox。请注意,数组是引用类型。实际上,您只是添加了对 ListBox 的引用,而不是数组的副本。
  3. 改变了数组的一个元素。这也会影响添加到 ListBox 的第一项,因为它包含对这个唯一数组的引用。
  4. 相同的数组引用作为项目添加到 ListBox。现在 ListBox 包含 2 个项目,它们引用具有相同元素的相同数组。

如果您希望项目包含 2 个不同的数组,您可以克隆该数组:

string[] s = new string[] { "5", "2", "3" };
listbox.Items.Add(s);
var s2 = (string[])s.Clone();
s2[2] = "0";
listbox.Items.Add(s2);

现在您在 ListBox 中有两个不同的项目。请注意,Array.Clone 方法会创建一个浅克隆。即数组元素本身没有被克隆。因此,如果它们是引用类型,则两个数组将在克隆后包含相同的对象。但是由于您有 2 个不同的数组,您可以替换数组的元素而不影响另一个数组。

您可以将克隆方法添加到您自己的类中

public class MyOwnClass
{
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }

    public MyOwnClass ShallowClone()
    {
        return (MyOwnClass)MemberwiseClone();
    }
}

MemberwiseClone继承自System.Object


推荐阅读