I have been wondering, why isn't my method, modifying the array, when I used it as a parameter and made it equal to another array with different values, inside the method? Am I just changing the reference address?
static void Main()
{
string[] array = { "yes", "no", "maybe" };
TestO(array); // Still "yes", "no", "maybe"
}
static void TestO(string[] array)
{
string[] secondArray = new string[array.Length];
secondArray[0] = "1";
secondArray[1] = "2";
secondArray[2] = "3";
array = secondArray;
}
My guess: I did not modify the array inside the Main(), because when doing array = secondArray;
in the Test0()
method,
I just changed the reference address of array
to secondArray
.
If my guess is not right, my question is, why exactly is it not getting modified?
(I know that I can just modify Test0()
to a string[]
return method and return the modified secondArray
and pass it on to the array
in Main()
)
Another questions is:
If I use the string[]
return method, and declare the following:
static void Main()
{
string[] array = { "yes", "no", "maybe" };
array = TestO(array);
}
static string[] TestO(string[] methodArray)
{
string[] secondArray = new string[methodArray.Length];
secondArray[0] = "1";
secondArray[1] = "2";
secondArray[2] = "3";
return secondArray;
}
array = TestO(array);
am I just passing the reference address of the secondArray[]
to array[]
or am I passing only the values of it? (Most probably it will be the reference address, but I wanted to be sure if mistaken)
CodePudding user response:
I just changed the reference address of array to secondArray. If my guess is not right, my question is, why exactly is it not getting modified?
I think you're leaning towards appreciating that there are two references to one data in memory (there are not two data); you have a variable array
that points to data. You call a method and another, copy reference is established to the same data. You made a new object, then you pointed the copied reference at the new object, leaving the original reference pointing to the original data, then you threw the copy reference and the new data away.. You're back to the exact same situation you started with.
Pictorially, line by line, it might look like (I renamed your method argument to arrayX
so the difference is obvious):
If you decorate the argument with ref
and call it with ref
there is no copy, so the called method can modify the original reference and point it somewhere else:
Note that in either of these cases it's perfectly possible to modify the contents of the array. Doing:
arrayX[0] = "New data";
..would take effect in either case and printing array[0]
would show "New data". When modifying the data at the end of the arrow it matters not whether the starting point is an original reference or a copy. This is purely about whether the method has the power to point the original reference passed to it, to a different object or not
Generally we don't do it. We adopt the style of your second code block - to return the data. It may help to see it as rude - imagine your friend says he'll look after your plant while you're on holiday; you give your keys to your friend. He swaps your plant for a different one that he likes better; you're upset because you had that plant for ten years..
There are very few reasons to use ref
, or the related "power to overwite your reference" - out
. Don't use it for "I wanted to return multiple things from my method" - in an OO world we can always return one thing that represents two items of data. We don't need to "return two things"; we can return one thing with two things inside it...
//don't:
void GetPerson(ref string name, ref int age)
//consider a class:
Person GetPerson()
return new Person(){ Name = ..., Age = ...}
//or a Tuple
(string Name, int Age) GetPerson
Let the calling method choose whether its own variable should be overwritten, rather than having some "third party" pull that rug from under its feet
CodePudding user response:
you don't need to return anything , just use a ref
static void Test( ref string[] array)
{
string[] secondArray = new string[array.Length];
secondArray[0] = "1";
secondArray[1] = "2";
secondArray[2] = "3";
array = secondArray;
}
CodePudding user response:
When you pass an array to a method
static void Test0(string[] array)
{
You are passing a reference to that array. That reference is effectively immutable (you're getting a copy of the reference, not the original one), so you can't change the parameter reference and expect it to affect the code outside of the Test method.
While you can do this to get the behavior you want:
static void Test0(ref string[] array)
{
it's not considered good C# style. Strings are themselves immutable; the "correct" style is to return them from the method. This is also true of string arrays.
The only thing you would be saving by using this technique is an extra reference and a return
statement, since you're still creating new strings and a new array anyway.