2

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?

D Stanley
  • 149,601
  • 11
  • 178
  • 240
freewill
  • 1,111
  • 1
  • 10
  • 23
  • 2
    it's bad (unusual) practice to use an underscore in parameter names. – Mitch Wheat Nov 12 '13 at 22:58
  • 3
    Also: "When I dont see ref keyword; it makes me worried" - erm, why? I think you meant that the other way around. – Mitch Wheat Nov 12 '13 at 22:59
  • I would really recommend you to look up C# a bit more @freewill. Also, try doing experiments with `ref`, `out`, classes and structs untill you are really sure what the differences are. – flindeberg Nov 12 '13 at 23:05
  • 1
    possible duplicate of [Passing properties by reference in C#](http://stackoverflow.com/questions/1402803/passing-properties-by-reference-in-c-sharp) – H H Nov 12 '13 at 23:06
  • 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. – Tim S. Nov 12 '13 at 23:08
  • @Mitch Wheat; No I mean what I wrote. Your comments forces me to study more; why should avoid ref/out keyword in most cases. – freewill Nov 12 '13 at 23:29
  • @Mitch Wheat. Thanks for the underscore hint. I always learn from experienced developers. I used underscore most time for local parameter of same of a public field. – freewill Nov 12 '13 at 23:31
  • this looks a lot like the post here: http://stackoverflow.com/questions/1402803/passing-properties-by-reference-in-c-sharp that may be helpful with trying to pass properties by reference. – Erick Nov 12 '13 at 22:59
  • Could somone please tell me the reason on hold of this question is because it has a possible duplicate? Everyone is saying this has a possible duplicate but I disagree. The reference question offers a solution for passing properties as reference where as I am asking a fundemantal question to understand better. If you say this information can be obtained by reading C# books; then I say O.K. This question helped me a lot to understand and the discussion with the "ref" keyword with experienced developers direct me in the right way. I am now using Method result classes instead of ref. – freewill Nov 16 '13 at 22:06

3 Answers3

7

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.

Michael Edenfield
  • 28,070
  • 4
  • 86
  • 117
  • 1
    Very well-explained Michael, +1. – Brian Nov 12 '13 at 23:18
  • 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 Nov 12 '13 at 23:21
  • 3
    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, – Michael Edenfield Nov 13 '13 at 00:47
  • 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. – freewill Nov 17 '13 at 00:57
1

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.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • 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. – freewill Nov 12 '13 at 23:42
0

This has less to do with pass by reference than you might think.

You have method ChangeCountry(Address a) that accepts an object of type Address

Instead of passing it an Address object you are passing it the String property (Country) of the address object when you call ChangeCountry(adr.Country).

To make your code modify the Address object you need to call the ChangeCountry(adr).

RangerRick
  • 51
  • 4