开发者

Unable to update the contents of a Generic List

开发者 https://www.devze.com 2023-01-28 00:18 出处:网络
I have a simple class which has boolean field: public struct Foo { bool isAvailable; } Now I have a List of foos:

I have a simple class which has boolean field:

public struct Foo { bool isAvailable; }

Now I have a List of foos:

List < Foo >  list = new List< Foo >();

Later on I enumerate each foo in the list and try to update its isAvailable field:

开发者_运维知识库foreach(Foo foo in list) {
    foo.isAvailable = true; 
}

But the above code never updates the list. What am I doing wrong here and what's its remedy.


It's because Foo is a mutable struct.

When you fetch the value from the list, it's making a copy - because that's how value types behave. You're changing the copy, leaving the original value unchanged.

Suggestions:

  • You probably should be using a class
  • Don't create mutable structs. They behave in ways which can be hard to predict, or at least not the way you might expect when you're not explicitly thinking about it.

While you could change your code to iterate over the list in a different way and replace the value each time, it's generally a bad idea to do so. Just use a class... or project your list to a new list with the appropriate values.


Original answer, when Foo was a class

It should work fine. For example, here's a short but complete program which does work:

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);
    }
}

Try to adapt your current code to a similar short but complete program which doesn't work, post that, and we can work out what's going on.


You're using a struct as Foo, not a class. Structs are copied, not referenced, and therefore you only modify the copy and not the object stored in the list.

So you basically have two options:

  • Make it a class

  • Re-assign the result to the list. To do so, I'd iterate using an index instead of using foreach.


When you fill list, you need to create new istance for each Foo Class.

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);

if you fill on this way:

List list = new List(); Foo foo = new Foo(); list.Add(foo); list.Add(foo); list.Add(foo);

you are reference on same memory location on stack for each object.

0

精彩评论

暂无评论...
验证码 换一张
取 消