Passing parameters by reference

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • developing
    New Member
    • Mar 2007
    • 110

    #1

    Passing parameters by reference

    Code:
     private char[] getSeparators(ref string[] varfiles)
    Code:
     private char[] getSeparators(string[] varfiles)

    As far as I know, the first piece of code will pass varfiles by reference so that varfiles will be changed by getSeparators when control is passed back to the calling method.


    What gets passed to getSeperators by the second piece of code?
  • Curtis Rutland
    Recognized Expert Specialist
    • Apr 2008
    • 3264

    #2
    Objects are always passed via reference, so there should be no difference between the two snippets you just posted.

    Comment

    • mldisibio
      Recognized Expert New Member
      • Sep 2008
      • 191

      #3
      Actually, this is tricky, and I myself get muddled by it every time. Nonetheless a great question!

      In the second snippet, you are indeed passing a reference to the array, but reference is an address, equivalent of a pointer. And since the ref keyword is not used, you are sending a copy of that address/pointer. That means, if you "point" the pointer to a new object/address/array, the original pointer remains intact and continues to point to the original array.

      In the first snippet, you pass the pointer by reference, meaning if you "point" the pointer to a new object/address/array, the original pointer now also points to the new object (and leaves the original array with no pointer/reference pointing to it...it is now orphaned).

      Below is a slightly modified but simple demonstration that can be found on MSDN or in books which discuss this subtle issue.

      Code:
        class RefAndValTest {
          static void Main(string[] args) {
            SendArrayByVal();
            SendArrayByRef();
          }
          // ==============================================================
          // Pass a ref type (class, interface, delegate, object, string) by val and create a new memory allocation
          //  Inside Caller, before calling the method, the first element is: 1
          //  Inside the method, the first element is: -3
          //  Inside Caller, after calling the method, the first element is: 888
          // ==============================================================
          static void SendArrayByVal() {
            int[] arr = { 1, 4, 5 };
            System.Console.WriteLine("SendArrayByVal()");
            System.Console.WriteLine("Inside Caller, before calling the method, the first element is: {0}", arr[0]);
      
            ModifyArray(arr);
            System.Console.WriteLine("Inside Caller, after calling the method, the first element is : {0}", arr[0]);
          }
          static void ModifyArray(int[] pArray) {
            pArray[0] = 888;  // This change affects the original element.
            pArray = new int[5] { -3, -1, -2, -3, -4 };   // This change is local.
            System.Console.WriteLine("Inside the method, the first element is                       : {0}", pArray[0]);
          }
          // ==============================================================
          // Pass a ref type (class, interface, delegate, object, string) by ref and create a new memory allocation
          //  Inside Caller, before calling the method, the first element is: 1
          //  Inside the method, the first element is: -3
          //  Inside Caller, after calling the method, the first element is: -3    
          // ==============================================================
          static void SendArrayByRef() {
            int[] arr = { 1, 4, 5 };
            System.Console.WriteLine("SendArrayByRef()");
            System.Console.WriteLine("Inside Caller, before calling the method, the first element is: {0}", arr[0]);
      
            ModifyArrayByRef(ref arr);
            System.Console.WriteLine("Inside Caller, after calling the method, the first element is : {0}", arr[0]);
          }
          static void ModifyArrayByRef(ref int[] pArray) {
            pArray[0] = 888;  
            pArray = new int[5] { -3, -1, -2, -3, -4 };  // new memory is allocated to parameter
            System.Console.WriteLine("                       Inside the method, the first element is: {0}", pArray[0]);
          }
       }

      Comment

      • mldisibio
        Recognized Expert New Member
        • Sep 2008
        • 191

        #4
        However, to clarify, insertAlias is correct in this sense: as long as you don't point the [ref varfiles] parameter to a completely new array, then in fact both methods simply modify the original array which is a reference object, and you would observe no difference.

        Therefore, except for the specific need to replace the original object with a completely new instance, the ref keyword is not needed for passing objects, and in fact it is more robust NOT to use it, so that you don't expose the original object to accidental "orphanage" or replacement if never intended.

        Finally, (for others reading this) remember that in the above explanations "object" means a reference type and not a value type, such as integers and booleans.

        Comment

        • Curtis Rutland
          Recognized Expert Specialist
          • Apr 2008
          • 3264

          #5
          Very good explanation.

          Comment

          • Frinavale
            Recognized Expert Expert
            • Oct 2006
            • 9749

            #6
            Originally posted by mldisibio
            In the second snippet, you are indeed passing a reference to the array, but reference is an address, equivalent of a pointer. And since the ref keyword is not used, you are sending a copy of that address/pointer. That means, if you "point" the pointer to a new object/address/array, the original pointer remains intact and continues to point to the original array.
            Thanks for that clarification! I had forgotten this bit of information.


            For a bit more information on ByRef and ByVal (in VB.NET) check out this post.

            :)

            -Frinny

            Comment

            • developing
              New Member
              • Mar 2007
              • 110

              #7
              Originally posted by mldisibio
              In the second snippet, you are indeed passing a reference to the array, but reference is an address, equivalent of a pointer. And since the ref keyword is not used, you are sending a copy of that address/pointer. That means, if you "point" the pointer to a new object/address/array, the original pointer remains intact and continues to point to the original array.

              That's what I came up with except I didn't know how to test it.

              For the two snippets above, I wasn't really concerned about the end result of the function, just wanted to see the "inner workings" because yeah, both will return a char[] except the first snippet doesn't really need to.


              Thanks for all the replies and clearing that up!

              Comment

              Working...