我想知道为什么当我们通过调用p = new Person("TOM", 999);
fred.PrintInfo();
时
它不会将p改为TOM和999,而是使用p.age = 99;我们可以很好地改变fred的年龄,构造函数和属性都是公共的,那么我在这里缺少什么?我不想对这段代码做任何事我只是想要原因。
using System;
class Person
{
public string fullName;
public int age;
public Person(string n, int a)
{
fullName = n;
age = a;
}
public void PrintInfo()
{
Console.WriteLine("{0} is {1} years old", fullName, age);
}
}
class MainClass
{
public static void SendAPersonByValue(Person p)
{
p.age = 99;
p = new Person("TOM", 999);
}
public static void Main()
{
Person fred = new Person("Fred", 12);
fred.PrintInfo();
SendAPersonByValue(fred);
fred.PrintInfo();
}
}
答案 0 :(得分:20)
fred
指向内存中的某个特定位置:
+------------+
fred ----> | Fred 12 |
+------------+
调用SendAPersonByValue后,p
指向同一位置:
+------------+
fred ----> | Fred 12 |
+------------+
^
p ---------+
p.age = 99;
现在更改了内存中的值:
+------------+
fred ----> | Fred 99 |
+------------+
^
p ---------+
而new Person("TOM", 999);
在内存中创建了一个 new Person,p = ...
使p
指向它:
+------------+
fred ----> | Fred 99 |
+------------+
+------------+
p ----> | TOM 999 |
+------------+
这正是fred
仍包含Fred, 99
的原因。
现在,如果您将fred
作为ref
parameter传递,p
将成为fred
的别名:
+------------+
fred/p ----> | Fred 12 |
+------------+
p.age = 99
之后:
+------------+
fred/p ----> | Fred 99 |
+------------+
p = new Person("TOM", 999);
之后:
+------------+
| Fred 99 | (will be garbage collected eventually)
+------------+
+------------+
fred/p ----> | TOM 999 |
+------------+
答案 1 :(得分:4)
因为只是Person p
的参考传递而不是参考的参考。
您需要执行此操作才能通过引用传递Person。:
public static void SendAPersonByValue(ref Person p)
{
p.age = 99;
p = new Person("TOM", 999);
}
答案 2 :(得分:2)
如果您希望main中的人员引用更改为新引用,则必须将ref放入参数列表中。否则,堆栈具有对主要使用的位置的引用。它可以更改内部属性,但不能更改引用,而引用主要保存到它传入的项目。
答案 3 :(得分:1)
这是因为您创建了一个新参考。如果您想要您期望的行为,则必须将SendAPersonByValue方法更改为ref Person p
。
所以,这里发生的是:
SendAPersonByValue(fred);
//You are passing the value of fred's reference here
...
public static void SendAPersonByValue(Person p)
{
p.age = 99;
//The value of Fred's reference is used to populate his age
p = new Person("TOM", 999);
//p is now assigned to a totally new reference.
//Because value's are immutable, fred remains
//However, p is now pointing to a different reference value
}
将ref添加到方法签名时会发生什么:
SendAPersonByValue(ref fred);
//A reference (pointer) to Fred's reference value is passed
...
public static void SendAPersonByValue(Person p)
{
p.age = 99;
//The pointer of the reference of Fred is used to populate his age
//Ultimately, this is the same as above because the both end up at Fred
p = new Person("TOM", 999);
//The reference value of p (fred) is now the new reference
//since it was just a pointer to the reference value
}
Here is a good article on the subject of values and references
答案 4 :(得分:1)
在方法SendAPersonByValue(Person p)
中分配变量p时,只能在本地分配。它不会在主方法中更改fred
。
您可以在主方法中返回修改后的人并替换fred,也可以使用ref
关键字。