再看下List的代码实现方式 private static readonly T[] _emptyArray = new T[0]; private const int _defaultCapacity = 4; private T[] _items; private int _size; private int _version; [NonSerialized] private object _syncRoot;。。 public void Add(T item) { if (this._size == this._items.Length) this.EnsureCapacity(this._size + 1); this._items[this._size++] = item; ++this._version; } 从这看出List的底层还是数组
在来用数组同样的实现下 class Program { static void Main(string[] args) { List<UserInfo> list = new List<UserInfo>(); UserInfo u = new UserInfo(); UserInfo[] us = new UserInfo[3]; u.UserName = "aaa"; us[0] = u; list.Add(u); u.UserName = "bbb"; us[1] = u; list.Add(u); Console.WriteLine(list[0].UserName); Console.ReadLine(); } } public class UserInfo { public string UserName { get; set; } }在想想数组的原理(C中的)得出结果是 list.add添加的是UserInfo的地址引用,改变UserName的值,修改了UserInfo对象所在的内存地址(因为C#是引用传递啊,这里就是引用传递),所以被修改了
只是你把u的UserName改变了
你应该这样:
UserInfo u1=new UserInfo{UserName="aaa"};
list.Add(u1);UserInfo u2=new UserInfo{UserName="bbb"};
list.Add(u2);或者直接使用C# 的集合初始化器:List<UserInfo> list=new List<UserInfo>
{
new UserInfo{UserName="aaa"},
new UserInfo{UserName="bbb"}
}
所以你先list.add(u),再u.name="aaa";list里面的那个u的name也变成aaa了。
如果你懂指针的话,这个很容易理解(c#里面没有指针,我是指思想)。
深层原因见你楼上13楼。
用白话说,如果没记错的话,就是你存到list里面的是指向U这个对象的路径,类似指针。当你修改的时候是修改的对象存储空间里面的值,所以当你程序运行的时候,由于你已经在对象的存储空间里面的值已经被修改,所以对应的取的值在你修改之后也发生了变化。PS:N久没看书了,原理大致如此吧,如有错误,请轻喷……
--- D:\Projects\Test\Test\Program.cs -------------------------------------------
{
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,50h
00000009 mov esi,ecx
0000000b lea edi,[ebp-38h]
0000000e mov ecx,0Bh
00000013 xor eax,eax
00000015 rep stos dword ptr es:[edi]
00000017 mov ecx,esi
00000019 xor eax,eax
0000001b mov dword ptr [ebp-1Ch],eax
0000001e mov dword ptr [ebp-3Ch],ecx
00000021 cmp dword ptr ds:[049714A4h],0
00000028 je 0000002F
0000002a call 76364477
0000002f xor edx,edx
00000031 mov dword ptr [ebp-44h],edx
00000034 xor edx,edx
00000036 mov dword ptr [ebp-40h],edx
00000039 xor edx,edx
0000003b mov dword ptr [ebp-48h],edx
0000003e nop
List<UserInfo> list = new List<UserInfo>();
0000003f mov ecx,49725E4h
00000044 call FD95FC20
00000049 mov dword ptr [ebp-4Ch],eax
0000004c mov ecx,dword ptr [ebp-4Ch]
0000004f call 76AA1190
00000054 mov eax,dword ptr [ebp-4Ch]
00000057 mov dword ptr [ebp-40h],eax
UserInfo u = new UserInfo();
0000005a mov ecx,4972590h
0000005f call FD95FC20
00000064 mov dword ptr [ebp-50h],eax
00000067 mov ecx,dword ptr [ebp-50h]
0000006a call FD97A438
0000006f mov eax,dword ptr [ebp-50h]
00000072 mov dword ptr [ebp-44h],eax
UserInfo[] us = new UserInfo[3];
00000075 mov edx,3
0000007a mov ecx,30A7B3Eh
0000007f call FD95FD54
00000084 mov dword ptr [ebp-54h],eax
00000087 mov eax,dword ptr [ebp-54h]
0000008a mov dword ptr [ebp-48h],eax
u.UserName = "aaa";
0000008d mov edx,dword ptr ds:[01B72088h]
00000093 mov ecx,dword ptr [ebp-44h]
00000096 cmp dword ptr [ecx],ecx
00000098 call FD97A430
0000009d nop
us[0] = u;
0000009e push dword ptr [ebp-44h]
000000a1 mov ecx,dword ptr [ebp-48h]
000000a4 xor edx,edx
000000a6 call 76160434
list.Add(u);
000000ab mov edx,dword ptr [ebp-44h]
000000ae mov ecx,dword ptr [ebp-40h]
000000b1 cmp dword ptr [ecx],ecx
000000b3 call 76AA1140
000000b8 nop
u.UserName = "bbb";
000000b9 mov edx,dword ptr ds:[01B7208Ch]
000000bf mov ecx,dword ptr [ebp-44h]
000000c2 cmp dword ptr [ecx],ecx
000000c4 call FD97A430
000000c9 nop
us[1] = u;
000000ca push dword ptr [ebp-44h]
000000cd mov ecx,dword ptr [ebp-48h]
000000d0 mov edx,1
000000d5 call 76160434
list.Add(u);
000000da mov edx,dword ptr [ebp-44h]
000000dd mov ecx,dword ptr [ebp-40h]
000000e0 cmp dword ptr [ecx],ecx
000000e2 call 76AA1140
000000e7 nop
Console.WriteLine(list[0].UserName);
000000e8 mov ecx,dword ptr [ebp-40h]
000000eb xor edx,edx
000000ed cmp dword ptr [ecx],ecx
000000ef call 76A347D0
000000f4 mov dword ptr [ebp-58h],eax
000000f7 mov ecx,dword ptr [ebp-58h]
000000fa cmp dword ptr [ecx],ecx
000000fc call FD97A428
00000101 mov dword ptr [ebp-5Ch],eax
00000104 mov ecx,dword ptr [ebp-5Ch]
00000107 call 76A44CAC
0000010c nop
Console.ReadLine();
0000010d call 770183B8
00000112 nop
}
00000113 nop
00000114 lea esp,[ebp-0Ch]
00000117 pop ebx
00000118 pop esi
00000119 pop edi
0000011a pop ebp
0000011b ret
private static readonly T[] _emptyArray = new T[0];
private const int _defaultCapacity = 4;
private T[] _items;
private int _size;
private int _version;
[NonSerialized]
private object _syncRoot;。。 public void Add(T item)
{
if (this._size == this._items.Length)
this.EnsureCapacity(this._size + 1);
this._items[this._size++] = item;
++this._version;
}
从这看出List的底层还是数组
{
static void Main(string[] args)
{
List<UserInfo> list = new List<UserInfo>();
UserInfo u = new UserInfo();
UserInfo[] us = new UserInfo[3];
u.UserName = "aaa";
us[0] = u;
list.Add(u);
u.UserName = "bbb";
us[1] = u;
list.Add(u);
Console.WriteLine(list[0].UserName);
Console.ReadLine();
}
}
public class UserInfo
{
public string UserName { get; set; }
}在想想数组的原理(C中的)得出结果是 list.add添加的是UserInfo的地址引用,改变UserName的值,修改了UserInfo对象所在的内存地址(因为C#是引用传递啊,这里就是引用传递),所以被修改了
实例化一次就够了..
改变UserName的值,修改了UserInfo对象所在的内存地址(因为C#是引用传递啊,这里就是引用传递),所以被修改了这是不对的 改变UserName的值,不会改变UserInfo对象所在的内存地址,UserName是UserInfo的一个字段
,你改变的UserName的值的时候,UserName的地址不会变化,变化的是它指向的对象,因为它是引用类型。
这就是.net让人不爽的地方
foreach(DataRow dr in dt.Rows){
UserInfo user=new UserInfo();
user.UserName=dr["UserName"].ToString();
list.Add(user);
}
return user;跟你的
List<UserInfo> list=new List<UserInfo>();
UserInfo u=new UserInfo();
u.UserName="aa";
list.Add(u);
u.UserName="bb";
list.Add(u)
return list;
你自己去比较区别,我看得懂你这是这块没理解透彻
开始没懂原理,我看你是没看懂我们在说什么,new 两个对象得到两个不同的地址,值会一样才怪,上面这题是无意中偷懒出现的,所有来弄明白原来,抱着不懂就问的心态,问题一出就要直捣老巢的学习方式。