Why doesn't the constructor affect the properties in this example

I'm wondering why, when we have p = new Person("TOM", 999);

, calling fred.PrintInfo();

It doesn't change p to TOM and 999, but using p.age = 99; we can change the age of fred and both constructors and properties are public, then, what's here that I'm missing? I don't want to do anything with this code, I just need a reason.

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

      

+3


source to share


5 answers


fred

points to a specific location in memory:

           +------------+
fred ----> | Fred    12 |
           +------------+

      

When calling SendAPersonByValue p

points to the same location:

           +------------+
fred ----> | Fred    12 |
           +------------+
              ^
  p  ---------+

      

p.age = 99;

now changes the value in memory:

           +------------+
fred ----> | Fred    99 |
           +------------+
              ^
  p  ---------+

      

whereas it new Person("TOM", 999);

creates a new Person in memory and p = ...

points p

to it:

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

           +------------+
  p  ----> | TOM    999 |
           +------------+

      



And that's why fred

it still contains Fred, 99

.


Now, if you need to pass fred

as a parameter ref

, p

it will be an alias for fred

:

             +------------+
fred/p ----> | Fred    12 |
             +------------+

      

After p.age = 99

:

             +------------+
fred/p ----> | Fred    99 |
             +------------+

      

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

:

             +------------+
             | Fred    99 |    (will be garbage collected eventually)
             +------------+

             +------------+
fred/p ----> | TOM    999 |
             +------------+

      

+20


source


Because the link Person p

is simply passed not by the link link .

You need to do this in order to transfer the Personality by reference .:



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

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

      

+4


source


If you want the person's link in the main text to change to a new link, you need to put the ref in the parameter list. Otherwise, the stack has a reference to where it is primarily used. It can change internal properties, but not the link that belongs to the main element that it passed.

+2


source


This is because you created a new link. If you want the behavior you expected, you will have to change the SendAPersonByValue method to ref Person p

.

So here's what's going on here:

SendAPersonByValue(fred);
//You are passing the value of fred reference here
...
public static void SendAPersonByValue(Person p)
{
    p.age = 99;
    //The value of Fred reference is used to populate his age

    p = new Person("TOM", 999);
    //p is now assigned to a totally new reference.
    //Because value are immutable, fred remains
    //However, p is now pointing to a different reference value
}

      

What happens when you add ref to your method signature:

SendAPersonByValue(ref fred);
//A reference (pointer) to Fred 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 meaning and links

+1


source


When you assign a variable p in a method SendAPersonByValue(Person p)

, you are only assigning it locally. It doesn't change fred

in your main method.

You can revert the changed person and replace fred in the main method, or use a keyword ref

.

+1


source







All Articles