想象一下这个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[]
之类的数组中更改它时,它没有任何错误。当使用泛型集合时,我的代码是否有任何问题?
答案 0 :(得分:13)
当您通过struct
索引器返回List[]
时,它会返回条目的副本。因此,如果您在那里分配了FirstName
,它就会被丢弃。因此编译错误。
将您的Person
重写为参考类型class
,或者进行全面重新分配:
Person person = list[1];
person.FirstName = "F22";
list[1] = person;
一般来说,可变的结构会带来诸如此类的问题,这些问题可能导致头痛。除非您有充分的理由使用它们,否则您应该强烈考虑更改Person
类型。
答案 1 :(得分:4)
显然问题的一部分仍然没有答案。 List<Person>
和Person[]
之间有何区别?在按索引获取元素方面,List
调用返回值类型实例副本的索引器(方法),在索引的相反数组中,不返回副本,而是在索引处返回元素的托管指针(使用特殊的IL指令{ {3}})。
当然,其他答案中提到的可变价值类型是邪恶的。看一下这个简单的例子。
var en = new {Ints = new List<int>{1,2,3}.GetEnumerator()};
while(en.Ints.MoveNext())
{
Console.WriteLine(x.Ints.Current);
}
惊奇?
答案 2 :(得分: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
的复制语义引起的。使它不可变并在这些约束下工作,问题就消失了。