有人可以解释一下这个
的行为 class testCompile
{
/*
* Sample Code For Purpose of Illustration
*/
struct person
{
public int age;
public string name;
}
static void Main(string[] args)
{
List<person> Listperson = new List<person>();
person myperson = new person();
for (int i = 1; i <= 2; i++)
{
//Assignment
myperson.age = 22+i;
myperson.name = "Person - " + i.ToString();
Listperson.Add(myperson);
}
int x = 0;
while (x < Listperson.Count)
{
//Output values
Console.WriteLine("{0} - {1}", Listperson[x].name, Listperson[x].age);
x++;
}
}
}
/*
Output:
Person - 1 - 23
Person - 2 - 24
*/
为什么我没有获得与结构类相同的输出?
class testCompile
{
/*
* Sample Code For Purpose of Illustration
*/
class person
{
public int age;
public string name;
}
static void Main(string[] args)
{
List<person> Listperson = new List<person>();
person myperson = new person();
for (int i = 1; i <= 2; i++)
{
//Assignment
myperson.age = 22+i;
myperson.name = "Person - " + i.ToString();
Listperson.Add(myperson);
}
int x = 0;
while (x < Listperson.Count)
{
//Output values
Console.WriteLine("{0} - {1}", Listperson[x].name, Listperson[x].age);
x++;
}
}
}
/*
Output:
Person - 2 - 24
Person - 2 - 24
*/
答案 0 :(得分:17)
类是引用类型,结构是值类型。
当值类型作为参数传递给方法时,它的副本将被传递。这意味着您添加了Person
结构的两个完全独立的副本,循环中每次传递一个。
当引用类型作为参数传递给方法时,引用将被传递。这意味着您将两个引用副本添加到同一个内存位置(对于同一个Person
对象) - 在对这一个对象进行更改时,您会看到它反映在两个引用中他们都引用同一个对象。
答案 1 :(得分:5)
值类型(struct)和引用类型(class)之间的区别。
当你将结构添加到Listperson
时,人的内容被放入列表中,你的列表中有两个不同的人结构。
for (int i = 1; i <= 2; i++)
{
//Assignment
myperson.age = 22+i;
myperson.name = "Person - " + i.ToString();
Listperson.Add(myperson);
/* First time:
Listperson contains a person struct with value { age = 23, name = 1}
Second iteration:
Listperson contains a person struct with value { age = 23, name = 1}
Listperson contains another person struct with value { age = 24, name = 2}
*/
}
当您添加类时,引用放在列表中,您有两个引用引用同一个人对象的引用。
for (int i = 1; i <= 2; i++)
{
//Assignment
myperson.age = 22+i;
myperson.name = "Person - " + i.ToString();
Listperson.Add(myperson);
/* First time:
Listperson contains 1 reference to myperson object with value { age = 23, name = 1}
Second iteration:
Listperson contains 2 reference to myperson object with value { age = 24, name = 2}
*/
}
答案 2 :(得分:4)
因为你的myperson变量只处理一个人结构/类。
在循环中添加到列表中的是myperson变量的副本 - 对于struct,它将是struct的完整副本,但是对于类,将是引用的副本到您创建(和变异)的单个实例。
答案 3 :(得分:4)
如果你想要相同的结果,那么在for循环中引入person声明: -
// person myperson = new person();
//Move the upper line inside the for loop
for (int i = 1; i <= 2; i++)
{
person myperson = new person();
//Assignment
myperson.age = 22+i;
myperson.name = "Person - " + i.ToString();
Listperson.Add(myperson);
}
在struct中添加值类型因此存储了单独的值,而在类中,您添加了对象的引用,因此得到相同的值。
答案 4 :(得分:2)
在第二个实例中,您要添加引用类型。事实上,自你的
以来,你要添加两次相同的项目 = new person()
不在循环中。所以它总是指向你在这里初始化的同一个对象:
person myperson = new person();
即使将其添加到您的列表中,更改也会影响它。
在第一个实例中,您每次都添加一个结构,这是一个值类型,因此将被复制到列表中。在此之后所做的更改不再引用列表中的对象,因此它们具有不同的值。
答案 5 :(得分:2)
结构是值类型,类是引用类型。因此,在第一个示例中,当您向列表中添加myperson时,添加myperson的副本和myperson变量仍然引用单独的副本。在第二个示例中,myperson是一个引用类型,因此您可以添加两个指向同一对象的指针。
答案 6 :(得分:2)
你应该理解结构(Value Types)和类(Reference Type)之间的关键区别。您可以在Google或SO
中轻松找到此信息将结构实例添加到List时,您为此实例创建另一个单独的副本,当您更改一个元素时,您没有更改另一个元素。
但是在类的情况下,你创建一个实例并使用这个“共享”实例和两个引用(list [0]和list 1),你可以通过两个不同的引用来改变这个实例,这就是为什么当您更改列表[0]项时,您似乎也更改了列表1项。
请考虑以下代码:
var s1 = new SampleStruct { X = 1, Y = 1 };
var s2 = s1;
//Creating separate copy
//Lets check this
Console.WriteLine(object.ReferenceEquals(s1, s2)); //Prints False
var c1 = new SampleClass { X = 1, Y = 2 };
var c2 = c1;
//We do not create any copy
// two references c1 and c2 "pointed" to one shared object
Console.WriteLine(object.ReferenceEquals(c1, c2)); //Prints True
当我们将参数传递给函数(或将元素添加到列表中)时,我们有类似的行为。
答案 7 :(得分:1)
在第二个示例中,您只是在项目上创建并多次添加对列表的引用。
答案 8 :(得分:1)
将结构添加到集合时,它会复制它。它是值类型。您最终会在集合中使用两个不同的对象,每个对象具有不同的值。这可能是预期的行为。
将类引用类型添加到集合时,不会创建新对象。您实际上是在同一个对象中添加了两个不同的引用。你最终会得到(显然)具有相同值的两个对象。它实际上是同一个对象,似乎在集合中出现了两次。
答案 9 :(得分:0)
将类类型的变量和参数视为持有“实例ID”。实际上可以直接使用实例ID做的事情是(1)创建一个新的(将分配给一个新的类实例),(2)将一个分配给另一个,或者(3)检查两个ID到看他们是否平等。使用类类型的变量,参数等执行任何其他操作都是“对执行此实例ID的实例执行 _ ”的简写。
所以代码如下:
{ Car A,B,C; /* Car is a class */ A = new Car; B = new Car; C = A; A.color = carColors.Yellow; B.color = C.color; }
第一个“new”语句将创建一个Car实例并将其实例ID(假设为#1234)放在“A”中。第二个将创建另一个汽车实例(#4321)并将其ID存储在B中。下一个语句将#1234复制到C中。它对汽车没有任何作用 - 它只是复制ID。然后汽车#1234将被涂成黄色,然后在最后的陈述中,汽车#1234(即黄色)的颜色将用于涂漆汽车#4321。请注意,虽然A和C是不同的变量,但它们都拥有相同的实例ID(#1234),因此引用同一辆车。