0

below is some very simple code that will highlight my problem/question

static void Main(string[] args)
{
    var myInitialString = "My Initial String";
    Console.WriteLine($"{nameof(myInitialString)}: {myInitialString}");
    MyMethod(myInitialString, MyRefMethod(ref myInitialString));
    Console.ReadLine();
}

static void MyMethod(string myVariableString, string otherString)
{
    //Prints out "My Initial String"
    Console.WriteLine($"MyString in myMethod: {myVariableString}");
}

static string MyRefMethod(ref string myRefString)
{
    myRefString = "MyEdittedString";
    Console.WriteLine($"{nameof(myRefString)} = {myRefString}");
    return "OtherString";
}

If I debug this and put a watch on myInitialString I can see that its value is "My Editted String" just before it goes into MyMethod and remains at that value. However the myVariableString argument has the value of "My Initial String". This seems to imply that the variable value had been captured before the second parameter, which is a method had been evaluated.

If I make a call to the MyRefMethod seperately before calling MyMethod, it works as I'd expect, it prints "My Editted String". If I swap the arguments so the call to MyRefMethod represents the first argument passed to MyMethod, it also prints out "My Editted String".

Which leads me to my question: How and when are the arguments that are passed to a method captured? Is the behavior displayed above to be expected?

Edit: Just to clarify as the question has been marked a duplicate potentially. This isn't a question about the difference between reference and value types and passing them around. As someone has pointed out below, this behavior would be the same with a value type

Dave
  • 2,829
  • 3
  • 17
  • 44
  • 2
    Possible duplicate of [What is the difference between a reference type and value type in c#?](https://stackoverflow.com/questions/5057267/what-is-the-difference-between-a-reference-type-and-value-type-in-c) – xxbbcc Oct 16 '17 at 13:24
  • 2
    @sumeetkumar There would be no differences anywhere in this code if anything was changed to be a value type instead of a reference type or vice versa. At no point in the code shown is it relevant. You could replace all of the strings with, say, integers, and the code would do the same thing. – Servy Oct 16 '17 at 13:24

1 Answers1

6

The arguments for a method are evaluated in order, from left to right, not from right to left. This means that the first argument is getting the value of the variable, then the second argument's expression is evaluated, changing the value of the variable, and then there is nothing left to observe that change.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • I did think that but I'm guessing the place it stores them isnt visible when degubbing as after the call to myRefMethod, I could see that myInitialString now had its new value, but as scope moved into myMethod, that argument myVariableString got the initial value, which is what has thrown me a little. – Dave Oct 16 '17 at 13:53
  • So just to clarify, method calls that will return something that will be used as an argument are not evaluated first? A bit like brackets in a mathematical equation – Dave Oct 16 '17 at 14:12
  • @Dave Arguments are evaluated from left to right. Always. – Servy Oct 16 '17 at 14:14