1

I found this method at this question

public static void RemoveAt<T>(ref T[] arr, int index)
{
    for (int a = index; a < arr.Length - 1; a++)
    {
        arr[a] = arr[a + 1];
    }
    Array.Resize(ref arr, arr.Length - 1);
}

Now I wanted to know if ref is required if it is used within a nested method? So could be the method also:

public static void RemoveAt<T>(T[] arr, int index) //ref removed

with the same functionality? I already tested it and it worked - but that means you could change reference without passing Ref Keyword. You just could do it in a sub method.

Toshi
  • 2,532
  • 4
  • 17
  • 45
  • 2
    @FCin but if I resize the Array, I technically create a new one and the pointer needs to be changed – Toshi Aug 20 '18 at 10:07
  • Possible duplicate of [Are arrays or lists passed by default by reference in c#?](https://stackoverflow.com/questions/967402/are-arrays-or-lists-passed-by-default-by-reference-in-c) – 41686d6564 stands w. Palestine Aug 20 '18 at 10:09
  • 3
    "I already tested it and it worked" - by "worked" do you mean "it compiles" or "the method behaves as it's meant to". I suspect you mean the first, not the second. – Damien_The_Unbeliever Aug 20 '18 at 10:09
  • Yes, it is required if you want the change made by the sub-method to propagate out of the current method. – juharr Aug 20 '18 at 10:25

2 Answers2

0

but that means you could change reference without passing Ref Keyword. You just could do it in a sub method

That's not true. Although you could change the reference within your RemoveAt-method, that change won't affect the reference passed to it. You just throw the new (resized) instance away. When you want to change the reference to point to some other instance, your method should have the ref-keyword.

In other keywords your second code could also be written like this:

public static void RemoveAt<T>(arr, int index)
{
    for (int a = index; a < arr.Length - 1; a++)
    {
        arr[a] = arr[a + 1];
    }
    var reference = arr;
    Array.Resize(ref reference, arr.Length - 1);
}

While reference would of course change after calling Array.Resize, arr will stay the same. They reference completely different instances.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
0

The functionality won't be the same. Resize can change the reference to arr, so in the first case you'd be changing an external reference of the caller, and without ref you'll only be changing the local method reference.

With ref:

var extArr = new object[100];

RemoveAt(ref extArr, 10); // The arr variable in this method is now the exact same physical
                          // variable as extArr.

// extArr is now a completely valid reference to the resized array, business as usual.

Without:

var extArr = new object[100];

RemoveAt(extArr , 10); // The copy of the reference (arr) is updated in this method 
                       //internally, but the local variable extArr is only copied and not modified

// extArr is now a reference to the old, not-resized array. 
// Note that the element is still "removed", overwritten in the for loop,
// but the resized copy of the array is lost and has no references to it.
V0ldek
  • 9,623
  • 1
  • 26
  • 57
  • 2
    `arr` will not be an invalid reference It will still be a perfectly valid reference to an 100 element array. You don't get invalid references in C#. That's part of what makes them references and code safe. – Damien_The_Unbeliever Aug 20 '18 at 10:11