8

想象一下struct

        struct Person
        {
             public string FirstName { get; set; }
             public string LastName { get; set; }
        }

以下代码:

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

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

Can't modify the expression because it's not a variable

同时,当我尝试在数组中更改它时,例如Person[]它可以正常工作而没有任何错误。与泛型集合一起使用时,我的代码有任何问题吗?

4

3 回答 3

14

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

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

Person person = list[1];
person.FirstName = "F22";
list[1] = person;

一般来说,可变结构会带来诸如此类的问题,这些问题可能会在未来引起头痛。除非您有充分的理由使用它们,否则您应该强烈考虑更改您的Person类型。

为什么可变结构是“邪恶的”?

于 2013-02-18T20:59:43.820 回答
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);
}

惊讶吗?

于 2013-02-19T13:04:33.350 回答
0

像这样重做struct

    struct Person
    {
         private readonly string firstName;
         private readonly string lastName;
         public Person(string firstName, string lastName)
         {
             this.firstName = firstName;
             this.lastName = lastName;
         }
         public string FirstName { get { return this.firstName; } }
         public string LastName { get { return this.lastName; } }
    }

以下代码为:

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

    // Can modify the expression because it's a new instance
    list[1] = new Person("F22", list[1].LastName);

这是由于struct. 使其不可变并在这些约束内工作,问题就会消失。

于 2013-02-18T21:26:15.393 回答