none
C# - passing reference with value RRS feed

  • Question

  • Hello,

    Why can we modified elements of object (This behavior seems to fly in the face of what it means to pass a parameter by value) but we cannot reassign new instance for it?

    Given that I were able to change the incoming Person, What was copied?  

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace ConsoleApp1
    {
        class Person
        {
            public Person() { }
            public string Name;
            public int Age;
    
            public Person(string name,int age)
            {
                Name = name;
                Age = age;
            }
    
            public void Display()
            {
                Console.WriteLine($"Name: {Name} - Age: {Age}");
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person("Daniel",20);
                Console.WriteLine("Before Send");
                p.Display();
                Change(p);
                Console.WriteLine("After Send");
                p.Display();
            }
            static void Change(Person p)
            {
                p.Age = 100; //modified
                p = new Person("Nikki",50); // NOT possible to reassign
            }
        }
    
    }





    • Edited by Arash_89 Saturday, October 12, 2019 9:32 PM
    Saturday, October 12, 2019 8:33 PM

All replies


  • Why we can modified elements of array (This behavior seems to fly in the face of what it means to pass a parameter by value) 

    Arrays (C# Programming Guide)
    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/

    "Array types are reference types derived from the abstract base type Array."

    Passing arrays as arguments (C# Programming Guide)
    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/passing-arrays-as-arguments

    "Arrays can be passed as arguments to method parameters. Because arrays are 
    reference types, the method can change the value of the elements."

    - Wayne

    Saturday, October 12, 2019 9:21 PM
  • I edited the question. 

    Why can we modified element of object but we cannot reassign new instance to it?

    Saturday, October 12, 2019 9:31 PM
  • I really don't know what you are talking about, but the below statment can be what is below it 

    p = new Person("Nikki",50); // NOT possible to reassign

    You just made a new object p aka Person that has values assigned to the properties.   and you don't need the Person constructor, which is kind of old school in this situation.

    p = new Person{name="Nikki", age=50};

    Here is anothher example of object intalizaton and values being assigned to object properties.

    public async Task<List<DtoArticle>> GetArticlesByAuthorId(int id)
            {
                var dtos = new List<DtoArticle>();
    
                var articles = await pc.Article.Where(a => a.AuthorId.ToString().Contains(id.ToString())).ToListAsync();
               
                foreach (var article in articles)
                {
                    var intid = (int)article.AuthorId;
    
                    var dtoauthor = await _daoAuthor.Find(intid);
    
                    var dto = new DtoArticle
                    {
                        ArticleId = article.ArticleId,
                        AuthorId = article.AuthorId,
                        AuthorName = dtoauthor.LastName +", " + dtoauthor.FirstName,
                        Title = article.Title,
                        Body = article.Body
                    };
    
                    dtos.Add(dto);
                }
                 
                return dtos;
            }

    using System;
    
    namespace Entities
    {
        public class DtoArticle
        {
            public int ArticleId { get; set; }
            public string Title { get; set; }
            public string Body { get; set; }
            public int AuthorId { get; set; }
            public string AuthorName { get; set; }
        }
    }
    

    Saturday, October 12, 2019 9:38 PM

  • Why can we modified element of object but we cannot reassign new instance to it?

    After you do the new the argument p then points to the local instance of Person.
    From that point on if you change members of the object pointed to by p you will
    be altering the local object, not the object in the caller. For example:

    static void Change(Person p)
    {
        p.Age = 100; //modified
        p = new Person("Nikki", 50); // p now points to the new local object
        p.Display(); // shows Nikki 50
        p.Age = 75; // changes Nikki's age to 75
        p.Display(); // shows Nikki 75
    }
    

    - Wayne

    Saturday, October 12, 2019 9:44 PM
  • For more details I changed example code here:

    As you can see, the value of personAge has been modified. This behavior seems to fly in the face of what it means to pass a parameter by value.

    Given that we were able to change the state of the incoming Person, what was copied?(It is call by value)

    Why can't we reassign a new instance for it? (but can modify it)


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace RefTypeValTypeParams
    {
        #region Simple Person class
        class Person
        {
            public string personName;
            public int personAge;
    
            // Constructors.
            public Person(string name, int age)
            {
                personName = name;
                personAge = age;
            }
            public Person() { }
    
            public void Display()
            {
                Console.WriteLine("Name: {0}, Age: {1}", personName, personAge);
            }
        }
        #endregion
    
        class Program
        {
            static void Main(string[] args)
            {
               
                Person mel = new Person("Mel", 23);
                Console.WriteLine("Before by value call, Person is:");
                mel.Display();
    
                SendAPersonByValue(mel);
                Console.WriteLine("After by value call, Person is:");
                mel.Display();
                Console.ReadLine();
    
            }
    
            #region Helper functions
            static void SendAPersonByValue(Person p)
            {
                // Change the age of "p"?
                p.personAge = 99;
    
                // Will the caller see this reassignment?
                p = new Person("Nikki", 99);
            }
    
            #endregion
        }
    }



    • Edited by Arash_89 Saturday, October 12, 2019 10:20 PM
    Saturday, October 12, 2019 10:07 PM

  • As you can see, the value of personAge has been modified. This behavior seems to fly in the face of what it means to pass a parameter by value.

    Given that we were able to change the state of the incoming Person, what was copied?(It is call by value)


    Classes are reference types just as are arrays. When you pass a class object as
    an argument to a method you are passing a *reference* to that object.

    - Wayne

    Saturday, October 12, 2019 11:05 PM
  • Hi Arash_89,

    Thank you for posting here.

    You want to know why reference can't pass value according to your code.

     p.personAge = 99;

    This code could change value successfully because it belongs to current instance p.

    p = new Person("Nikki", 99);

    The second code could not change the value because it create a new instance p, which is different from the former instance p. It is only a local variable. Meanwhile, the code will choose the former instance p. Therefore, it will not change the value.

    Hope his could help you.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, October 14, 2019 2:57 AM
    Moderator
  • When using reference type, then by default you can change the values of the referenced object of argument. That means you can change for examle name of Person class instance. What you can not do is change the location where, reference, that instance is referencing. If you want to change the reference of the argument, then you need to pass it by-reference. Using ref key word in C#. Then you can also assign new or some other reference.

    So method needs following signature and because ref key word now also caller of method is aware that reference might change.

    // Passing Person by reference
    static void Change(ref Person p)
    {
         p.Age = 100; //modified
         p = new Person("Nikki",50); // Now possible
    }


    Monday, October 14, 2019 4:37 AM
  •  Using ref key word in C#. Then you can also assign new or some other reference.


    All method parameters are passed by value unless you specifically see ref or out.

    C# Arrays are reference types. This means that you're passing a reference by value.

    Saturday, December 21, 2019 4:35 AM