2

I have a char array in one method, someObject is an arbitrary object passed by reference to the GetChars method:

private void DoSomeStuff(ref Object someObject)
{
   char[] chars = GetChars(ref someObject); // {'a','b','c','d'}
   char[] ReversedChars = Reverse(chars); // {'d','d','b','a'}
   //chars and ReversedChars are in the same order, although "ref" is not used
}

private char[] Reverse(char[] someChars)
{
   Array.Reverse(someChars);
   return someChars;
}

Why is Array.Reverse in another method changing the original passed char array if not passing it by reference?

kataba
  • 93
  • 6
  • Why are your reference type arguments marked `ref` when you never assign to them? Do you understand what `ref` means and what a reference type is? – 15ee8f99-57ff-4f92-890c-b56153 May 10 '19 at 15:25
  • Because it is a temporary object I use, but even if we imagine that someObject parameter does not exist the result will be the same probably. – kataba May 10 '19 at 15:30
  • [`ref` has nothing to do with whether the parameter is a temporary object](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref). – 15ee8f99-57ff-4f92-890c-b56153 May 10 '19 at 15:33
  • The method reverse its design to modify the array pass to it as a reference (https://learn.microsoft.com/en-us/dotnet/api/system.array.reverse?view=netframework-4.8). If you wish to ensure that the original is not affected, then clone the array, reverse the cloned array, and return the such clone. – acarlstein May 10 '19 at 15:36
  • Try `char[] clone = (char[]) Array.Clone(someChars);`. Then, `Array.Reverse(clone);` and finally `return clone;` – acarlstein May 10 '19 at 15:39
  • @EdPlunkett, it is true that I am not reassigning the reference to someObject in the methods. I did it because I thought that if I pass with "ref" then it will be more optimized performance-wise because I was thinking that passing it without "ref" will create a new clone of "someObject". – kataba May 10 '19 at 17:21
  • @kataba That is incorrect: Passing it without ref will pass a reference to `someObject`. Nothing new will be created. The reference `someObject` inside the method is a reference to the same actual object that you passed in, unless you assign a new object to the reference inside the method. In that case, if it's `ref`, the new object will be assigned to the outside reference too. If not `ref`, `someObject` inside the function will refer to the new object, and the refrence outside the function will still refer to what it used to. That's what `ref` does. – 15ee8f99-57ff-4f92-890c-b56153 May 10 '19 at 17:24

3 Answers3

3

Arrays are objects, so: reference-types.

It is passing a reference - by value. So: if you change what the reference points to (i.e. the array data), that change will still be visible to everyone who also has a reference to that same object.

There is only one array here; there is literally no other data that could be changed.

Passing a reference by-reference is only meaningful if you will reassign the reference to a different object.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

Arrays are reference types (they are a kind of object according to .NET). When you call your routine you are returning the same reference, and are only changing the order of the elements within it.

Copy the array before you reverse the results if you want it not to effect the original.

Steve Todd
  • 1,250
  • 6
  • 13
  • "Arrays are always passed by reference" - that's very ambiguous, since "reference" has two distinct meanings in this context; arrays are objects, the values of locals / fields / parameters etc that touch objects *are* references, but those parameters are *almost always* passed by-value, not by-reference - so saying "passed by reference" is ... unhelpful IMO; in the case of the code shown in the question, the value *is* a reference, and it it is passed *by* value – Marc Gravell May 10 '19 at 15:26
  • I'll accept that this could be clearer, I'll edit the text a little – Steve Todd May 10 '19 at 15:30
1

As an array is a referenced type, you would need to make a copy of your array if you do not want to affect your original values.

To do so, update your Reverse method to this:

private char[] Reverse(char[] someChars)
    {
        char[] cloneArray = someChars.Clone() as char[];
        Array.Reverse(cloneArray);
        return cloneArray;
    }
Lionize
  • 51
  • 3