无法更改泛型集合中struct的成员值

sab*_*ber 8 .net c# struct generic-list generic-collections

想象一下struct:

        struct Person
        {
             public string FirstName { get; set; }
             public string LastName { get; set; }
        }
Run Code Online (Sandbox Code Playgroud)

以下代码:

        var list = new List<Person>();
        list.Add(new Person { FirstName = "F1", LastName = "L1" });
        list.Add(new Person { FirstName = "F2", LastName = "L2" });
        list.Add(new Person { FirstName = "F3", LastName = "L3" });

        // Can't modify the expression because it's not a variable
        list[1].FirstName = "F22";
Run Code Online (Sandbox Code Playgroud)

当我想要更改Property它的值时,它会给我以下错误:

Can't modify the expression because it's not a variable
Run Code Online (Sandbox Code Playgroud)

然而,当我试图在数组中更改它时,Person[]它没有任何错误.当使用泛型集合时,我的代码有什么问题吗?

Chr*_*air 13

当您struct通过List[]索引器返回时,它将返回条目的副本.所以,如果你分配FirstName那里,它就会被抛弃.因此编译错误.

要么将您重写Person为引用类型class,要么完全重新分配:

Person person = list[1];
person.FirstName = "F22";
list[1] = person;
Run Code Online (Sandbox Code Playgroud)

一般来说,可变结构带来了诸如此类的问题,这些问题可能导致头痛.除非你有充分的理由使用它们,否则你应该强烈考虑改变你的Person类型.

为什么可变结构"邪恶"?

  • +1你所展示的读取/修改/回写方法是恕我直言,这是最简单的编码方式,因为它非常明显地改变了结构的哪个部分.代码如`list [1] = new Person("F22",list [1] .LastName);`远不那么清楚,更可能是错误的[例如,如果`Person`有一个可选的`MiddleName`参数,后面的代码会意外地清除它 - oops]. (2认同)

Ham*_*yan 5

显然,问题的一部分仍未得到解答。有什么区别List<Person>Person[]。在按索引获取元素方面,List调用索引器(方法)返回值类型实例的副本,在相反的数组中按索引返回的不是副本,而是指向索引处元素的托管指针(使用特殊的 IL 指令ldelema)。

当然,正如其他答案中提到的那样,可变值类型是邪恶的。看一个简单的例子。

var en = new {Ints = new List<int>{1,2,3}.GetEnumerator()};
while(en.Ints.MoveNext())
{
    Console.WriteLine(x.Ints.Current);
}
Run Code Online (Sandbox Code Playgroud)

惊讶?