【问题标题】:Adding custom objects to checked list boxes in C#在 C# 中将自定义对象添加到选中的列表框
【发布时间】:2016-07-06 13:45:25
【问题描述】:

我有一个对象,它存储两个字符串并覆盖 ToString() 方法以返回其中一个字符串

            fooBar temp;
            foreach (string foo in bar)
            {
                temp = new fooBar(); <--- Why is this line needed when I 
                am overwriting the code and path on each cycle before adding?

                temp.code += ".";
                temp.path += ".";

                Console.WriteLine(temp);
                clbFooBar.Items.Add(temp);
            }

到控制台的打印遵循被覆盖的代码和路径字符串值,但是选中的列表框项都是完全相同的(最后一项的 ToString()),正在进行的底层过程不是很明显?

如果我将其更改为clbFooBar.Items.Add(temp.ToString());,它绝对可以正常工作,但这与temp.ToString.ToString() 不一样,因为.Add 首先调用.ToString()?我认为控制台打印和.Add 的行为相同,因为它们都调用ToString()

编辑:temp = new fooBar(); 是解决我的问题的方法,我只想知道为什么这是解决方法,因为直觉让我认为覆盖两个字符串(代码和路径)就足够了,为什么没有这个重新初始化时,选中列表框中的所有项目都是相同的。

【问题讨论】:

  • 如果您删除temp = new fooBar();这一行,它们是否相同?
  • 不,控制台打印和选中的列表框只有在该行存在时才会相互反映,这对我来说没有意义。
  • 我的意思是,如果该行 not 存在,则选中列表框中的项目看起来都相同,但如果该行 is 则(正确)不同> 现在?
  • 没错!同样, clbFooBar.Items.Add(temp.ToString()) 也可以,但我不确定这是否仍然允许我访问对象中的其他字符串。
  • 你能编辑问题并添加一个简单的代码来重现问题。包含您的课程。目前(对我来说)不清楚你在问什么。

标签: c# winforms checkedlistbox


【解决方案1】:

所以你的问题似乎是如果你保留这条线,为什么你的代码可以正常工作

temp = new fooBar();

在您的循环中,但如果您省略此行,则会用所有相等的项目填充您的 CheckedListBox

原因是,如果您像这样在循环之外创建 一个 fooBar 实例:

fooBar temp; = new fooBar();
foreach (string foo in bar)
{
    temp.code += ".";
    temp.path += ".";
    clbFooBar.Items.Add(temp);
}

然后您将多次添加同一个实例,并在每次迭代中更改该实例的属性

如果您像这样在循环中创建新实例

foreach (string foo in bar)
{
    fooBar temp; = new fooBar();
    temp.code += ".";
    temp.path += ".";
    clbFooBar.Items.Add(temp);
}

每次迭代都有一个新实例,不要更改已添加的实例。


更新:刚刚注意到,当您将它们全部设置为任何默认值 codetemp 加上 "." 时,它们看起来仍然相同。所以仍然有点不清楚你实际上试图做什么。也许是这样的:

string s = string.Empty;
foreach (string foo in bar)
{
    s += ".";
    fooBar temp; = new fooBar();
    temp.code = s;
    temp.path = s;
    clbFooBar.Items.Add(temp);
}

【讨论】:

  • 啊!因此,您要说的是,当前选中的列表框中的实例无论如何都反映了该实例,这就是为什么它们似乎都是最后一项,因为这就是添加所有项后的当前实例。我假设选中的列表框项目不是对您传递它的实例的引用,而是您传递的内容的副本。谢谢!
  • @Bradley:我的意思是,如果您只创建一个实例,那么就只有一个实例。是的,您将同一个实例多次插入到您的选中列表框中,并在每次迭代中更改了它的属性。所以最后的变化是你的checklistbox中显示的内容。
  • 非常感谢,这让我大吃一惊!周五了吗?
  • 在这种情况下,foreach 的意义何在?您没有在循环中使用变量。为什么不只用 bar 的计数做一个 while 循环?
  • 非常好。代码和路径在我的代码中使用 foo,我只是没有在我的示例中反映这一点,并且很快只是想说明每次传递时代码和路径的变化,抱歉。
【解决方案2】:

您在foreach 循环之外创建temp,然后在内部对其进行初始化。

如果您没有在每次循环时都重新初始化,那么您最终会得到一个CheckedListBox,其中所有项目都指向同一个对象。

这就是为什么您在查看列表时会获得最后一个对象的值(因为实际上只有一个)。

我猜您实际上想要做的是将 bar 中的每个项目 (foo) 添加到 CheckedListBox。如果是这样,请使用它。

        foreach (string foo in bar)
        {
            foo.code += ".";
            foo.path += ".";

            Console.WriteLine(foo);
            clbFooBar.Items.Add(foo);
        }

【讨论】:

  • 我不认为我解释得很好,正在发生完全相反的事情。如果我没有在每次传递时重新初始化,结果是整个选中的列表框包含似乎与最后一项重复的内容。
  • 是的,我明白了。问题正如我所描述的那样。你试过我的方法了吗?
  • 你的方法正是我的方法,也是我首先遇到问题的原因。重新初始化解决了问题,我只想知道为什么!哈哈
  • 实际上,如果您查看我的方法,我正在修改foo 变量的codepath 属性,在foreach 循环中初始化。您的代码使用的是在循环外初始化的 temp
  • 啊,是的,抱歉,我没有仔细阅读您的代码。 Temp 是我需要添加的对象,因为它包含两个我都需要的字符串,您将 foo 误认为是我正在使用的类型,字符串中不能有子字符串! :)
猜你喜欢
  • 2020-08-26
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
相关资源
最近更新 更多