struct UserInfo { public string Name; public int Age; public bool Gender; } class Program { static void Main(string[] args) { List<UserInfo> list = new List<UserInfo>() { new UserInfo { Name = "阿三", Age = 20, Gender = true }, new UserInfo { Name = "阿四", Age = 30, Gender = false }, new UserInfo { Name = "阿五", Age = 40, Gender = true } }; UserInfo[] uArr = list.ToArray(); uArr[0].Name = "xxx"; list[0].Name = "yyyy";// 上一句数组索引没报错,这句集合索引为什么报错了 Console.ReadLine(); } }
1、struct改为class没这个问题
2、var item = list[0];item.Name="yyyy";也不会有问题。
3、List是一个集合,Array是数组。数组和集合的处理方式是不同的。
4、如果是class,list[0].Name="yyyy";等价于var item = list[0];item.Name="yyyy";
而是struct的时候,struct的复制特性,其中的item本身不存在,导致赋值报告这个错误。
这个涉及到值类型与引用类型的概念
struct是值类型,list是引用类型:网上有个说法就是值类型就是现金,引用类型就是存折,数组你也可以看作值类型
那么uArr[0]就是现金,你可以直接使用
那么List[0]是存折,你不能直接用,要var item = list[0],先取出来,然后就可以用了
那么问题来了,改为class为什么又可以呢?我们来看看list[int]的源码
public List(int capacity) {
if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
Contract.EndContractBlock();
if (capacity == 0)
_items = _emptyArray;
else
_items = new T[capacity];
}
所以返回的是new T[capacity],实例化之后的,所以list[0]这个时候是可以直接复制的
可能你要问我struct的时候返回的也new T[capacity]啊。这个设计到装箱概念,值类型放到list里面是经过装箱动作,装箱实际上是拷贝一个副本,具体的可以了解装箱拆箱概念。