在扩展方法中更改数组大小不起作用?

mod*_*diX 4 c# arrays extension-methods concatenation unity-game-engine

所以基本上我Add为数组类型编写了我的小扩展方法。

using System;
using System.Linq;
public static class Extensions 
{
    public static void Add<T>(this T[] _self, T item)
    {
        _self = _self.Concat(new T[] { item }).ToArray();
    }
}
public class Program
{
    public static void Main()
    {
        string[] test = { "Hello" };
        test = test.Concat(new string[] { "cruel" }).ToArray();
        test.Add("but funny");
        Console.WriteLine(String.Join(" ", test) + " world");
    }
}
Run Code Online (Sandbox Code Playgroud)

输出应该是Hello cruel but funny world,但but funny永远不会在扩展方法中连接。

在扩展中编辑相同的数组似乎也不起作用:

using System;
using System.Linq;
public static class Extensions 
{
    public static void Add<T>(this T[] _self, T item)
    {
        Array.Resize(ref _self, _self.Length + 1);
        _self[_self.Length - 1] = item;
    }
}
public class Program
{
    public static void Main()
    {
        string[] test = { "Hello" };
        test = test.Concat(new string[] { "cruel" }).ToArray();
        test.Add("but funny");
        Console.WriteLine(String.Join(" ", test) + " world");
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里出了什么问题,我该如何使用它作为扩展?

.dotNet 小提琴:https://dotnetfiddle.net/9os8nYhttps://dotnetfiddle.net/oLfwRD

(如果能找到一种方法,这样我就可以保持通话,那就太好了test.Add("item");

Sel*_*enç 6

您正在为参数分配一个新的引用,除非您将其作为参数传递,否则它不会更改实际的数组ref。由于这是一种扩展方法,因此它不是一个选项。所以考虑使用正常的方法:

public static void Add<T>(ref T[] _self, T item)
{
    _self = _self.Concat(new T[] { item }).ToArray();
}

Add(ref test, "but funny");
Run Code Online (Sandbox Code Playgroud)

或者,如果您坚持使用扩展方法,则需要将数组设置为第二个参数才能使用 ref:

public static void AddTo<T>(this T item, ref T[] arr, )
{
    arr = arr.Concat(new T[] { item }).ToArray();
}

"but funny".AddTo(ref test);
Run Code Online (Sandbox Code Playgroud)

Array.Resize不起作用。因为它改变的是_self,而不是test数组。现在,当您传递不带关键字的引用类型时ref,该引用将被复制。是这样的:

string[] arr1 = { "Hello" };
string[] arr2 = arr1;
Run Code Online (Sandbox Code Playgroud)

现在,如果您为 分配一个新引用arr2,它不会更改 的arr1引用。Array.Resize所做的是,由于无法调整数组大小,因此它会创建一个新数组并将所有元素复制到新数组,然后分配该新引用因此它更改了 where指向的参数,但由于和是两个不同的引用(如和),因此更改其中一个不会影响另一个。_self_self_selftestarr1arr2

另一方面,如果您ref像我的第一个示例中那样将数组传递给您的方法,那么Array.Resize该方法也将按预期工作,因为在这种情况下,不会复制引用:

public static void Add<T>(ref T[] _self, T item)
{
    Array.Resize(ref _self, _self.Length + 1);
    _self[_self.Length - 1] = item;
}
Run Code Online (Sandbox Code Playgroud)