无法更新通用列表的内容

3

我有一个简单的类,其中有一个布尔字段:

public struct Foo { bool isAvailable; }

现在我有一个foo列表:
List < Foo >  list = new List< Foo >();

稍后我会枚举列表中的每个foo并尝试更新其isAvailable字段。
foreach(Foo foo in list) {
    foo.isAvailable = true; 
}

但上述代码从未更新列表。我在这里做错了什么?有什么解决办法。

你“忘记”发布相关代码片段了(其中可能包含错误)。请展示如何使用“Foo”的实例填充列表以及如何检查列表是否已更新。 - Doc Brown
2
你的 Foo 可能被声明为结构体而不是类吗? - Lucero
1
似乎你的字段是私有的。 - Tudor Olariu
谢谢Jon和大家,你们让生活变得如此简单。 - munna
3个回答

7
这是因为Foo是一个可变的结构体。
当您从列表中获取值时,它会进行复制 - 因为这就是值类型的行为方式。您更改了副本,使原始值保持不变。
建议:
  • 您可能应该使用类
  • 不要创建可变结构体。它们的行为方式可能很难预测,或者至少在您没有明确考虑时不是您期望的方式。
虽然您可以更改代码以以不同的方式迭代列表并每次替换值,但通常不建议这样做。只需使用类...或将您的列表投影到具有适当值的列表中即可。

原始答案,当Foo是一个类时

它应该正常工作。例如,这是一个短小但完整的程序,它可以工作:
using System.Collections.Generic;

public class Foo
{
    public bool IsAvailable { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return Name + ": " + IsAvailable;
    }
}

class Test
{
    static void Main()
    {
        List<Foo> list = new List<Foo>()
        {
            new Foo { Name = "First", IsAvailable = true },
            new Foo { Name = "Second", IsAvailable = false },
            new Foo { Name = "Third", IsAvailable = false },
        };

        Console.WriteLine("Before:");
        list.ForEach(Console.WriteLine);
        Console.WriteLine();

        foreach (Foo foo in list)
        {
            foo.IsAvailable = true;
        }

        Console.WriteLine("After:");
        list.ForEach(Console.WriteLine);
    }
}

尝试将您当前的代码调整为类似的简短但完整的程序,该程序无法正常工作,发布该程序后,我们可以找出问题所在。


嘿Jon,我正在使用IsAvailable作为字段,这会有什么区别吗?而Foo是一个结构体而不是一个类。 - munna
@munna:啊,重要的是它是一个结构体。我会进行编辑。 - Jon Skeet

2
您正在使用结构体作为Foo,而不是类。 结构体是复制而不是引用的,因此您只修改副本而不是存储在列表中的对象。
所以您基本上有两个选择:
  • 将其改为类

  • 重新分配结果到列表中。 为此,我将使用索引进行迭代,而不是使用foreach


0
当你填充列表时,需要为每个Foo类创建新的实例。
List list = new List(); Foo foo = new Foo();
foo.isAvailable = false; list.Add(foo);
foo = new Foo(); list.Add(foo);
foo = new Foo(); list.Add(foo);
如果你以这种方式填充:
List list = new List(); Foo foo = new Foo(); list.Add(foo); list.Add(foo); list.Add(foo);
你会引用堆栈中相同的内存位置来存储每个对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接