C# Properties as Reference

11,776

Solution 1

No, properties that are passed into methods are not modified in that method, because you cannot pass them by reference. Properties are always passed by value, so you cannot change their value within the methods that you pass them two.

However, that's not actually what you are doing in both methods, and that's why one works and one does not.

Your first method:

public void ChangeCountry(string _Country)
{
    _Country = "US";
}

attempts to change the value of the parameter that does not have the ref keyword, which fails (as you noted).

Your second method,

public void ChangeAddress(Address _adr)
{
    _adr.Country = "US";
}

is not trying to change the value of its parameter. The Address object that you pass into the method remains the same instance of Address for the entire method. However, because Address is a reference type, you can change its properties, and those changes will persist once the method returns. They will also be visible to any other places that have a reference to the same instance.

To see the difference, if you had tried to do this in your second method, it would have failed, for the same reason your first method does:

public void ChangeAddress(Address _adr)
{
    _adr = new Address();
    _adr.Country = "US";
}

Here, you are trying to change the value of the parameter -- to a new instance of the class -- and that doesn't work without the ref keyword.

Solution 2

When I see the ref keyword, it makes me worried. In the vast majority of cases, there is a better solution. ref and out should be used sparingly. I can see two fairly good ways to solve your problem, from what I can see in your example:

string GetNewCountry() { return "US"; } // pass in existing Address if needed

adr.Country = GetNewCountry();

// or

public void ChangeAddress(Address adr)
{
    adr.Country = "US";
}

To answer your second question, strings aren't particularly special, they are just another immutable type. If you study up on how references are passed and modified in C#, the behavior you see will be perfectly clear: in the one case, you are modifying the mutable Address object, and in the other, you are replacing the local variable with a reference to a different string object.

Share:
11,776
freewill
Author by

freewill

Updated on June 04, 2022

Comments

  • freewill
    freewill almost 2 years

    Basic fundamental I messed up with C# Properties and reference types.

    public Address adr { get; set; }
    
    public class Address
    {
    
        //Field
        public string AddressLine1;   
    
        //Property
        public string Country {get; set;}
    }
    
    public void ChangeCountry(string _Country)
    {
        _Country = "US";
    }
    
    public void ChangeAddress(Address _adr)
    {
        _adr.Country = "US";
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
        adr = new Address();
        ChangeCountry(adr.Country);
    
        MessageBox.Show(adr.Country);
        //(?)Country is reported empty string. Property did not updated outside.
    
        ChangeAddress(adr);
    
        MessageBox.Show(adr.Country);
        //OK. Country is reported 'US'
    
    
    }
    

    Here my questions;

    1. When we pass a Property(simple or complex one) directly to a method that will attempt to modify it, Is it ensured this property modified everywhere? I mean Like the ref keyword? Since I can't use the "ref" keyword with properties;I directly pass property to a method for modification and I'm not sure if it is always going to be updated/modified also at outside. When I dont see ref keyword; it makes me worried :)

    2. In the above example; adr class is updated successfully(ChangeAddress) without ref keyword; but the ChangeCountry method could not updated the string Country property. Is this a special case for strings?

  • Brian
    Brian over 10 years
    Very well-explained Michael, +1.
  • freewill
    freewill over 10 years
    Thank you. That's the exact description that address my problem and clears my doubts. However other friends pushes me hard not to use ref keyword :)
  • freewill
    freewill over 10 years
    Thanks Tim. I will follow your suggestions about ref/out and fundemantals. I have lots of methods running in an order; all have "ref ErrorStatus err" reference in method arguments; all these methods add their error status to this variable(like a logger). I will check if this can be done better upon your suggestions.
  • Michael Edenfield
    Michael Edenfield over 10 years
    There is nothing wrong with using ref parameters when they are needed, but you should make sure you really need them. Often times the desire to have ref parameters indicates a flaw in your design that could be solved in a better way,
  • freewill
    freewill over 10 years
    Thanks Michael I've studied deeper it. A cleaner, readable, better solution offered is to return a "Result" class instead of using ref or out variables. I was using always bool as "return" and ref/out for status code and error messages in methods. I thnik it comes from old habbits and old style programming. Now result class style looks really better. You have been very helpful. Thank you very much.