Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#列表<;T>;内部构件_C#_Generics_List - Fatal编程技术网

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