C#列表<;T>;内部构件
将对象添加到集合(如列表)时会发生什么情况C#列表<;T>;内部构件,c#,generics,list,C#,Generics,List,将对象添加到集合(如列表)时会发生什么情况 List<Person> people = new List<Person>(); Person dan = new Person() { Name="daniel", Age=10 }; people.Add(dan); dan = new Person() { Name = "hw", Age = 44 }; List people=newlist(); Person dan=新人(){Name=“daniel”,年龄=1
List<Person> people = new List<Person>();
Person dan = new Person() { Name="daniel", Age=10 };
people.Add(dan);
dan = new Person() { Name = "hw", Age = 44 };
List people=newlist();
Person dan=新人(){Name=“daniel”,年龄=10};
人。加上(丹);
dan=新人(){Name=“hw”,年龄=44};
当我执行上述代码时,列出人员
不受最后一行的影响。
因此,我假设列表复制了添加对象的引用,因此当更改引用时,列表不会受到影响。我说的对吗?好吧,您显示的代码实际上根本没有向列表中添加任何内容。我想你是想:
people.Add(dan);
在什么地方
但是是的,列表
包含对对象的引用。它不知道参考文献是从哪里来的。关于变量和它的值之间的区别,值得一提。当你打电话时:
people.Add(dan);
在本例中,它将参数表达式(dan
)的值复制为列表中参数的初始值。添加。该值只是一个引用-它与dan
变量没有关联,只是它恰好是调用List.Add
时变量的值
与以下情况完全相同:
Person p1 = new Person { Name = "Jon" };
p2 = p1;
p1 = new Person { Name = "Dan" };
这里,p2
的值仍然是对名为“Jon”的人的引用-第二行只是将p1
的值复制到p2
而不是将两个变量关联在一起。一旦您理解了这一点,就可以对方法参数应用相同的逻辑。好的,使用该代码,列出人员
也不应该受到第二行的影响
无论如何,如果您使用.Add()
,则列表将获得一个引用。因此,如果您稍后修改此人,列表中的此人也将被“修改”(是同一个人),但是如果您将此人分配给其他人,您不会影响引用,您将符号分配给新的引用
e、 g:
List people=newlist();
Person dan=新人(){Name=“daniel”,年龄=10};
人。加上(丹);
/*DanData={Name=“daniel”,年龄=10};
*`people[0]`映射到“DanData”
*`dan`映射到“DanData”*/
dan.Name=“丹尼尔第一”;
字符串dansNameInList=people[0]。名称;/*等于“丹尼尔第一”*/
/*DanData={Name=“丹尼尔第一”,年龄=10};
*`people[0]`映射到“DanData”
*`dan`映射到“DanData”*/
人物[0]。Name=“再次出现丹尼尔”;
字符串dansName=dan.Name/*再次等于“daniel”*/
/*DanData={Name=“daniel”,年龄=10};
*`people[0]`映射到“DanData”
*`dan`映射到“DanData”*/
dan=新人(){Name=“hw”,年龄=44};
字符串dansNameInListAfterChange=people[0]。Name/*等于“再次daniel”*/
字符串dansnamafterchange=dan.Name/*等于“hw”*/
/*DanData={Name=“daniel”,年龄=10};
*NewData={Name=“hw”,Age=44};
*`people[0]`映射到“DanData”
*`dan`映射到“NewData”*/
要回答原始问题,假设您打算在拨打第三行之前将此人添加到列表中:
是,列表仅存储对对象的引用。在C#中,所有对象变量都是引用
因此,当您第二次调用new Person()
时,变量dan
持有的引用将更新为指向新实例。如果第一个实例没有指向它的引用,它将在下一轮中被垃圾收集。如果已将第一个实例添加到列表中,列表仍将保留对第一个实例的引用。在代码末尾添加
people[0] = dan;
将指向新的dan对象。在.NET编程中,充分理解引用类型和值类型之间的差异非常重要。本文提供了一个很好的概述:
在本例中,您创建了两个Person对象(10岁的Daniel和44岁的hw)。是引用这两个对象的变量造成了混乱
在这里,一个局部变量dan被指定一个对新创建的(Daniel,10岁)对象的引用
在这里,属性people[0]被(间接地通过List.Add方法)分配了对现有(Daniel,10岁)对象的引用
在这里,局部变量dan被分配一个对新创建的(hw,44岁)对象的引用。但是属性people[0]仍然保留对现有(Daniel,10岁)对象的引用。在何处向列表添加对象?你能修好你的代码吗?哎呀!忘记添加对象。谢天谢地,stackoverflow的聪明头脑理解了我想要表达的意思。在你给出的p1和p2示例中,人“Jon”继续存在的唯一原因是p2=p1赋值,对吗?如果没有这个任务,那么如果我是对的,那么GC创建“Dan”的时候就会删除“Jon”的实例?谢谢。@Sabuncu:好吧,并不是“Dan”的创造“抹去”了另一个对象,而是事实上,没有更多的引用来保持另一个对象的生命。(请注意,没有什么好说的,当另一个对象被收集时。)将另一个对象的创建从GC方面分离出来是值得的。举例来说,这不是一个替代另一个。谢谢!这是一个简单的问题,但我知道答案,来自你,将是一个学习的经验。
people[0] = dan;
Person dan = new Person() { Name="daniel", Age=10 };
people.Add(dan);
dan = new Person() { Name = "hw", Age = 44 };