C# 为什么构造函数不';不影响本例中的属性

C# 为什么构造函数不';不影响本例中的属性,c#,C#,我想知道为什么我们有p=新人(“汤姆”,999)

我想知道为什么我们有
p=新人(“汤姆”,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();
    }
}

因为只传递
人员p
的引用而不是引用的引用

您需要这样做才能通过引用传递该人员:

public static void SendAPersonByValue(ref Person p)
{
    p.age = 99;

    p = new Person("TOM", 999);
}

这是因为您创建了一个新引用。如果希望实现预期的行为,则必须将SendPersonByValue方法更改为
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
}

如果您希望主体中的person引用更改为新引用,则必须将ref放入参数列表中。否则,堆栈将引用main使用的位置。它可以更改内部属性,但不能更改main对它传入的项的引用。

在方法
sendpersonbyvalue(Person p)
中指定变量p时,只能在本地指定它。它不会在您的main方法中更改
fred


您可以返回修改后的person并在main方法中替换fred,也可以使用
ref
关键字。

fred
指向内存中的某个特定位置:

           +------------+
fred ----> | Fred    12 |
           +------------+
           +------------+
fred ----> | Fred    99 |
           +------------+
              ^
  p  ---------+
调用sendpersonbyvalue时,
p
指向相同的位置:

           +------------+
fred ----> | Fred    12 |
           +------------+
              ^
  p  ---------+
p.age=99现在更改内存中的值:

           +------------+
fred ----> | Fred    12 |
           +------------+
           +------------+
fred ----> | Fred    99 |
           +------------+
              ^
  p  ---------+
鉴于
新人(“TOM”,999)
在内存中创建一个新的人,并且
p=…
使
p
指向它:

           +------------+
fred ----> | Fred    99 |
           +------------+

           +------------+
  p  ----> | TOM    999 |
           +------------+
这就是为什么
fred
仍然包含
fred,99


现在,如果您要将
fred
作为密码传递,
p
将成为
fred
的别名:

             +------------+
fred/p ----> | Fred    12 |
             +------------+
p.age=99后

             +------------+
fred/p ----> | Fred    99 |
             +------------+
之后
p=新人(“汤姆”,999)


读这个…:这是一个很好的老派视觉解释。喜欢图表中的加号、减号和管道。:)+1.回答这个问题。甚至帮助我更清楚地理解它。我非常喜欢它。谢谢你。我知道引用,但你在清除指针所做的事情方面帮了我很多。Approved一旦引用不再使用,它会立即被标记为垃圾收集。顺便说一句,干得好+1.